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 AJAX Basics (retiring) Programming AJAX Stage 2 Challenge

Getting Reusable Function to Work

I'm trying to get this function to work, so I can use again. Instead of duplicating a code.

function createList(requestName, variableName, key1, key2, idName) {
  if(requestName.readyState === 4 && requestName.status === 200) {
    var variableName = JSON.parse(requestName.responseText);
    var statusHTML = '<ul class="bulleted">';
    for (var i=0; i<variableName.length; i += 1) {
      if (variableName[i].key1 === true) {
        statusHTML += '<li class="in">';
      } else {
        statusHTML += '<li class="out">';
      }
      statusHTML += variableName[i].key2;
      statusHTML += '</li>';
    }
    statusHTML += '</ul>';
    document.getElementById(idName).innerHTML = statusHTML;
  }
}

var xhr = new XMLHttpRequest();

xhr.onreadystatechange = createList(xhr, employees, inoffice, name, 'employeeList' );
xhr.open('GET', '../data/employees.json');
xhr.send();

Can anyone help me to fix this?

//Fixed Code Presentation

3 Answers

Not sure if this is what you were going for too but I wanted to have the same code work for both instances since the requests were so similar. This is what I came up with

function getRequest(type, url) {
  var xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function() {
    if (xhr.readyState === 4 && xhr.status === 200) {
      var dataObject = JSON.parse(xhr.responseText);
      // set to empty string so it wont add to undefined string
      var htmlContent = "";
      var trueClass, falseClass, objectName, objectBoolean;
      if (type === 'room') {
        trueClass = 'empty';
        falseClass = 'full';
        objectName = 'room';
        objectBoolean = 'available';
      }
      if (type === 'employee') {
        trueClass = 'in';
        falseClass = 'out';
        objectName = 'name';
        objectBoolean = 'inoffice';
      }
      for (var i=0; i<dataObject.length; i += 1) {
        if (dataObject[i][objectBoolean]) {
          htmlContent += '<li class="' + trueClass +'">';
        } else {
          htmlContent += '<li class="' + falseClass +'">';
        }
        htmlContent += dataObject[i][objectName];
        htmlContent += '</li>';
      }
      // get the ul with the name of the list instead of writing the ul in here
      document.getElementById(type + 'List').innerHTML = htmlContent;
    }
  }
  xhr.open('GET', url);
  xhr.send();
}

getRequest('room', '../data/rooms.json');
getRequest('employee', '../data/employees.json');

Take a look at your line statusHTML += variableName[i].key2;

I know you're trying to use a parameter when the function is called, but that line looks like you're trying to call a property .key2 on variableName that already exists..

Try statusHTML += variableName[i].[key2]; to bring out the fact that key2 is a string variable containing the object property name..

I hope this helps, take care!

-- Cal

I came to a conclusion that xhr.onreadystatechange doesn't like any brackets. It only works when I create a variable and add an anonymous function to it and then simply add that variable to xhr.onreadystatechange.

Like this:

xhr.onreadystatechange = nameOfVariable;

But this wont work:

xhr.onreadystatechange = nameOfVariable();

Anyone know why?

Brendan Moran
Brendan Moran
14,052 Points

When you insert an anonymous function within a named variable, that is called a function expression.

When you put empty brackets after a function name (whether you used a function declaration or function expression to name it), you are calling that function, and the call is immediate. When the javaScript interpreter reads nameOfVariable(), it immediate funs the function called nameOfVariable of contained within nameOfVariable. So, in the case of an event listener (onreadystatechange is an event listener), you actually aren't waiting for the event listener to run the function if you put the () after it, you are running it as soon as the browsers JSI runs over that code. Take off the parentheses, as you discovered, and the function will only be run when the event fires.

Hope this help! This topic is covered in some more detail in Andrew Chalkley's "Interactive Web Pages With JavaScript Course": https://teamtreehouse.com/library/interactive-web-pages-with-javascript