Ad

Collecting Arrays From JSON Object And Element Class Names And Comparing Them

- 1 answer

I have an external JSON feed that displays room bookings for multiple rooms. The problem is that it only shows the timeslots that are booked and does not show empty slots/appointments in the data object. Issue is the feed does not contain the empty timeslots that have not been booked yet.

So I came up with an idea to have a preformatted HTML 'template' page with some data already present - effectively to overlay the JSON data in the booked timeslots and leave the empty timeslots as just static HTML.

Idea was to name the <td> elements with a class name that denotes the room id and the timeslot in 24hr time. Then to construct an array based on all the <td> class names. Then filter my JSON object bookings times and retrieve back an array that contained the room id and booking start time (amongst other necessary data).

Next step is to loop through both arrays and if there is a match against the room id and booking start time across both arrays, then print the data into that cell (which can be accessed via its class name). Right now, I am having problems with getting the arrays to look the same.

The 'simplified' JSON file (just a selection of whole object):

var response={
  "bookings": {
    "group_id": 12306,
    "name": "Public Meeting Rooms",
    "url": "http:theurlfeed.from.libcal",
    "timeslots": [{
      "room_id": "36615",
      "room_name": "Meeting Room 2A",
      "booking_label": "Mahjong",
      "booking_start": "2016-01-20T10:00:00+10:00",
      "booking_end": "2016-01-20T11:00:00+10:00"
    }, {
      "room_id": "36615",
      "room_name": "Meeting Room 2A",
      "booking_label": "Mahjong",
      "booking_start": "2016-01-20T11:00:00+10:00",
      "booking_end": "2016-01-20T12:00:00+10:00"
    }, {
      "room_id": "36616",
      "room_name": "Meeting Room 2B",
      "booking_label": "IELTS",
      "booking_start": "2016-01-20T10:00:00+10:00",
      "booking_end": "2016-01-20T11:00:00+10:00"
    }, {
      "room_id": "36616",
      "room_name": "Meeting Room 2B",
      "booking_label": "recording",
      "booking_start": "2016-01-20T12:00:00+10:00",
      "booking_end": "2016-01-20T13:00:00+10:00"
    }, {
      "room_id": "36616",
      "room_name": "Meeting Room 2B",
      "booking_label": "Luke",
      "booking_start": "2016-01-20T18:00:00+10:00",
      "booking_end": "2016-01-20T19:00:00+10:00"
    }],
    "last_updated": "2016-01-20T12:40:36+10:00"
  }
}

Here is the HTML (for the sake of simplification I haven't shown the complete structure):

<table border="1" id="rooms-table">
<thead><tr><th></th>&nbsp;<th>10am</th><th>11am</th><th>12pm</th><th>1pm</th><th>2pm</th><th>3pm</th><th>4pm</th><th>5pm</th><th>6pm</th><th>7pm</th></tr></thead>
<tbody id="main-table-body">
  <tr>
    <td>Meeting Room 2A</td>
    <td class="36615 10:00"></td>
    <td class="36615 11:00"></td>
    <td class="36615 12:00"></td>
  </tr>
  <tr>
    <td>Meeting Room 2B</td>
    <td class="36616 10:00"></td>
    <td class="36616 11:00"></td>
    <td class="36616 12:00"></td>
  </tr>
  <tr>
  </tbody>
  </table>

And this is my JavaScript (contains pseudo code at the bottom for concepts I have not yet coded):

//Convert timestamp to readable format and remove date
var Timeslots = response.bookings.timeslots;

function getTime(timestamp) {
    var time = new Date(timestamp);
    return [ time.getHours(), time.getMinutes() ].map(function(time){
        return ['', "0"][+(String(time).length < 2)] + String(time);
    }).join(':');
}                  

for(var i in Timeslots) (function(Timeslots){
    Timeslots.booking_start = getTime(Timeslots.booking_start);
    Timeslots.booking_end = getTime(Timeslots.booking_end);
})(Timeslots[i]);

console.log(response);

var roomList = new Array;
var tdClassList;

//function to detect if timeslot is booked or not
//If booked, assigns the booking name and changes bg color of cell
$.each(response.bookings.timeslots, function(index, timeslot) {

    var roomBooking = timeslot.room_id + ' ' + timeslot.booking_start;
    roomList[roomBooking] = roomBooking;

    tdClassList = $('td').map(function () {
        return $(this).attr('class');
    }).get();

    });
    console.log(tdClassList);
    console.log(roomList);
         // This code is incomplete
         // It will need to loop through both arrays and compare values and then write some css and html if match is found across the arrays
        /*if (roomList == tdClassName) {
            $( "td" ).html(timeslot.booking_label)
            $( "td" ).css( "background-color", "red" );
        } else { $( "td" ).html("");
        }*/

Here is a link to a working JS Fiddle showing all elements in play: https://jsfiddle.net/coolwebs/L0ybd0dm/1/

My issue right now is that the array that is being created from the JSON object is coming in as key value pairs.

Instead of returning:

["36615 10:00", "36615 11:00", "36615 12:00", "36615 30:00", ...]

It is returning:

[36615 10:00: "36615 10:00",36615 11:00: "36615 11:00", 36615 12:00: "36615 12:00", 36615 13:00: "36615 30:00", ...]

Um, what am I doing wrong?

Ad

Answer

This is far from perfect or complete but does simplify your process somewhat.

I don't see any need to create the cell array. Once you have parsed the incoming data, you can loop over the cells and do the matching right away.

I used a simple object to make the room/start comparison.

// example
var timeClasses ={"3456 02:00":true, "56854 11:00": true}

Then when you loop through the table it's a simple check to see if the property matching your cell classes exists

success: function(response) {  


    var data = response.bookings.timeslots;

    var timeClasses = {};

    var Timeslots = data.map(function(item) {
      // parse the dates
      item.booking_start = getTime(item.booking_start);
      item.booking_end = getTime(item.booking_end);
      // update hashmap
      timeClasses[item.room_id + ' ' + item.booking_start] = true;
      return item;
    });


    $('tbody tr').each(function() {
      $(this).find('td:gt(0)').each(function() {
        var className = $(this).attr('class');
        if (timeClasses[className]) {
          $(this).css('background', 'red')
        }
      });
    });

  }

This is really only intended to give you a starting point. I don't really like the classes methodology ...especially with the space in them.

You will also need to revisit how you will visualize the full timeslot that a booking covers and will need some more logic to apply for the cells in middle of each booking

DEMO

Ad
source: stackoverflow.com
Ad