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 Programming AJAX Programming AJAX Solution

Grzegorz Zielinski
Grzegorz Zielinski
5,838 Points

My solutions for this challenge - what do you think?

Any ideas how I could improve it or what I could change to make it look/work better?

function generateLi(positive, negative, list, first, second) {
  let listPosition = document.createElement("li");
  if (first === true) {
    listPosition.className = `${positive}`;
  } else if (first === false) {
    listPosition.className = `${negative}`;
  }
  listPosition.textContent = second;
  list.appendChild(listPosition);
}

var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    var target = JSON.parse(xhr.responseText);
    let list = document.querySelector("#employeeList");
    let listUl = document.createElement("ul");
    listUl.className = "bulleted";
    list.appendChild(listUl);
    for (let i = 0; i < target.length; i += 1) {
      let firstObject = target[i].inoffice;
      let secondObject = target[i].name;
      generateLi("in", "out", listUl, firstObject, secondObject);
    }
  }
};

xhr.open("GET", "data/employees.json");
xhr.send();

var xhr2 = new XMLHttpRequest();
xhr2.onreadystatechange = function () {
  if (xhr2.readyState === 4) {
    var target = JSON.parse(xhr2.responseText);
    let list = document.querySelector("#roomList");
    let listUl = document.createElement("ul");
    listUl.className = "rooms";
    list.appendChild(listUl);
    for (let i = 0; i < target.length; i += 1) {
      let firstObject = target[i].available;
      let secondObject = target[i].room;
      generateLi("empty", "full", listUl, firstObject, secondObject);
    }
  }
};

xhr2.open("GET", "data/rooms.json");
xhr2.send();

Thanks!

Trevor Maltbie
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Trevor Maltbie
Full Stack JavaScript Techdegree Graduate 17,021 Points

Nice solution! That is some good refactoring.

To keep that generateLI function smaller, I wonder if it could be refactored into a couple of functions?

5 Answers

  • I like how you thought about scalability. Your code would scale better than mine
  • I wish I thought about it when I was writing mine
// This is my code for comparison
const employees_List = new XMLHttpRequest();
employees_List.onreadystatechange = function() {
    if(employees_List.readyState === 4) {
        const employeeList = document.getElementById('employeeList');
        const employees = JSON.parse(employees_List.responseText);
        const ulElement = document.createElement('ul');
        ulElement.className = 'employees';
        employeeList.appendChild(ulElement);
        employees.forEach(element => {
            let liElement = document.createElement('li');
            if (element.inoffice === false) liElement.className = 'out';
            if (element.inoffice === true) liElement.className = 'in';
            liElement.textContent = element.name;
            ulElement.appendChild(liElement);
        });
    }
};
employees_List.open('GET','data/employees.json');
employees_List.send();

const roomsStatus = new XMLHttpRequest();
roomsStatus.onreadystatechange = function() {
    if(roomsStatus.readyState === 4) {
        const roomList = document.getElementById('roomList');
        const rooms = JSON.parse(roomsStatus.responseText);
        const ulElement = document.createElement('ul');
        ulElement.className = 'rooms';
        roomList.appendChild(ulElement);
        rooms.forEach(room => {
            let liElement = document.createElement('li');
            if (room.available === false) liElement.className = 'full';
            if (room.available === true) liElement.className = 'empty';
            liElement.textContent = room.room;
            ulElement.appendChild(liElement);
        });
    }
};
roomsStatus.open('GET', 'data/rooms.json');
roomsStatus.send();

I would suggest you to make it so that when you click on the 'room' or 'employee' it shows an alert. It's always good to take the code you learned a little further. Here's how my code works in action:

Grzegorz Zielinski
Grzegorz Zielinski
5,838 Points

Thank you, I totally agree with you, for sure I will take a look at it

I also like the way you've used to aim each of element in your code

employees.forEach(element => {})

Honestly I have to read about it a bit more cause it seems to be pretty useful thing when working with arrays/objects like in this case.

Btw. I took a look through your code I've also found a small mistake in it:

ulElement.className = 'employees';

Class name for this element should be "bulleted", unless you've changed a class name in your CSS file for this task by yourself to "employees" :)

Yea I changed it so that it makes more sense.

I like it! Here's mine :)

function employeeBuilder(data) {
  return (
    `<ul class='bulleted'>
      ${
        data.map(({inoffice, name}) => (
          `<li class=${inoffice ? 'in' : 'out'}>${name}</li>`
        ))
        .join('')
      }
    </ul>`
  );
};

function officeBuilder(data) {
  //room: 101, available: false
  return (
    `<ul class='rooms'>
      ${
        data.map(({available, room}) => (
          `<li class=${available ? 'empty' : 'full'}>${room}</li>`
        ))
        .join('')
      }
    </ul>`
  );
};

function xhrCallback(xhrRequest, listBuilder, className) {
  return function() {
    if(xhrRequest.readyState === 4) {
      const data = JSON.parse(xhrRequest.responseText);
      const html = listBuilder(data)
      const node = document.getElementById(className);
      node.innerHTML = html;
    }
  };
}

const employeeRequest = new XMLHttpRequest();
employeeRequest.onreadystatechange = xhrCallback(employeeRequest, employeeBuilder, 'employeeList');
employeeRequest.open('GET', 'data/employees.json');
employeeRequest.send();

const officeRequest = new XMLHttpRequest();
officeRequest.onreadystatechange = xhrCallback(officeRequest, officeBuilder, 'roomList');
officeRequest.open('GET', 'data/rooms.json');
officeRequest.send();
Blaize Pennington
Blaize Pennington
13,879 Points

I love these other options. They have given me a lot of ideas. Here is my working version:

const request = new XMLHttpRequest();
request.onreadystatechange = () => {
 if (request.readyState === 4) {
    if(request.status === 200) {
      const rooms = JSON.parse(request.responseText);
      const ul = document.createElement('ul');
      ul.className = "rooms";
      rooms.forEach(room => {
         const newLi = document.createElement('li');
         newLi.className = room.available ? "full" : "empty";
         newLi.textContent = room.room;
         ul.appendChild(newLi);
      });
      document.getElementById('roomList').appendChild(ul);
    }
    else {
      alert(request.status);
    }
 }
}
request.open("GET", '../data/rooms.json');
request.send();
Clayton Weymouth
Clayton Weymouth
8,770 Points

Here is my version:

const statusRequest = new XMLHttpRequest();
const roomRequest = new XMLHttpRequest();

const employees_path = '../data/employees.json';
const rooms_path = '../data/rooms.json';

const completeRequest = function(request, func, get_param) {
  request.onreadystatechange = function() {
    if (request.readyState === 4) {
      if (request.status === 200) {
        func(request.responseText);
      };
    };
  };
  request.open('GET', get_param);
  request.send();
};

const employeesWidget = function(responseText) {
  var employees = JSON.parse(responseText);
  var statusHTML = '<ul class="bulleted">';

  for (var i=0; i<employees.length; i += 1) {
    const name = employees[i].name;
    const status = employees[i].inoffice;

    if (status) {
      statusHTML += `<li class="in">${name}</li>`;
    } else {
      statusHTML += `<li class="out">${name}</li>`;
    }
  }
  statusHTML += '</ul>';
  document.getElementById('employeeList').innerHTML = statusHTML;
};

const roomsWidget = function(responseText) {
  var rooms = JSON.parse(responseText);
  var availableHTML = '<ul class="rooms">';

  for (var i=0; i<rooms.length; i += 1) {
    const room = rooms[i].room;
    const available = rooms[i].available;

    if (available) {
      availableHTML += `<li class="empty">${room}</li>`;
    } else {
      availableHTML += `<li class="full">${room}</li>`;
    }
  }
  availableHTML += '</ul>';
  document.getElementById('roomList').innerHTML = availableHTML;
};

completeRequest(statusRequest, employeesWidget, employees_path);
completeRequest(roomRequest, roomsWidget, rooms_path);