// --- Configuration ---------------------------------------------------- // Time range to display for timetable const startTime = "7:00"; const endTime = "19:00"; // Labels for days of the week. The timetable will have one // column for every entry here. const headersArray = [ "MON", "TUE", "WED", "THU", "FRI" ] // Two-dimensional array representing events. // Array format: [ event name, day of week, start time, end time, color ] const eventArray = [ [ "Example event", 1, "11:00", "14:00", "#3366AA"], [ "Thursday 1", 3, "9:30", "12:00", "#668811"], [ "Thursday 2", 3, "12:00", "13:30", "#668811"] ]; // Labels for each 30-minute block. By default, blocks are labeled in // one hour intervals. const timesArray = [ "0:00", "", "1:00", "", "2:00", "", "3:00", "", "4:00", "", "5:00", "", "6:00", "", "7:00", "", "8:00", "", "9:00", "", "10:00", "", "11:00", "", "12:00", "", "13:00", "", "14:00", "", "15:00", "", "16:00", "", "17:00", "", "18:00", "", "19:00", "", "20:00", "", "21:00", "", "22:00", "", "23:00", "", "00:00", "" ]; // ---- Code --------------------------------------------------------------- // A block's position in a day's column is used to locate said block. // So if the schedule starts at 7:00, then 7:00-7:30 will be block 0 // and 7:30-8:00 will be block 1. // Two-dimensional array representing X and Y // coordinates of blocks on the timetable. var blockArray = []; createTable(); addEvents(); // Create the empty timetable with columns for each day (and one // column for the time). function createTable() { var table = document.createElement("table"); table.id = "timetable"; document.getElementById("schedule-wrapper").appendChild(table); // Table header var header = document.createElement("tr"); header.className = "schedule-header"; addToTable(header); // Time column header var timehead = document.createElement("th"); timehead.className = "schedule-corner"; header.appendChild(timehead); // Add labels for days of the week for (let i = 0; i < headersArray.length; i++) { var heading = document.createElement("th"); heading.className = "schedule-heading"; heading.appendChild(document.createTextNode(headersArray[i])); header.appendChild(heading); } var tableBlocks = timeToBlockCount(startTime, endTime); // Cells for (let i = 0; i < tableBlocks; i++) { var row = makeRow(i); addToTable(row); blockArray[i] = []; // Time column var cell = document.createElement("td"); cell.className = "schedule-time"; // Create time label var label = timesArray[ Number(startTime.split(":")[0]) * 2 + i ]; cell.appendChild(document.createTextNode(label)); row.appendChild(cell); for (let j = 0; j < headersArray.length; j++) { var cell = makeCell(i, j); row.appendChild(cell); blockArray[i][j] = cell; } } } // Add events from the global events array to the timetable. function addEvents() { // Iterate through each event and add to table for (let event of eventArray) { // Retrieve starting cell var cell = blockArray[ timeToBlockPosition(event[2]) ][ event[1] ]; // Apply styling expandBlock(cell, timeToBlockCount(event[2], event[3])); cell.style.backgroundColor = event[4]; cell.appendChild(document.createTextNode(event[0])); } } // ---- Helper Functions ------------------------------------------------- // Returns the position of a block found at a given time (in) function timeToBlockPosition(time) { var parts = time.split(":"); return(parts[0] - startTime.split(":")[0]) * 2 + (parts[1] / 30); } // Returns how many 30-minute blocks the given hour range needs function timeToBlockCount(start, end) { var startParts = start.split(":"); var endParts = end.split(":"); var minutesSum; if (startParts[1] == endParts[1]) minutesSum = 0; else if (startParts[1] > endParts[1]) minutesSum = -1; else minutesSum = 1; return(((endParts[0] - startParts[0]) * 2) + minutesSum); } function addToTable(element) { document.getElementById("timetable").appendChild(element); } function makeCell(x, y) { var element = document.createElement("td"); element.id = x + "," + y; element.className = "schedule-cell"; return element; } function makeRow(id) { var element = document.createElement("tr"); element.id = id; element.className = "schedule-row"; return element; } function deleteCell(cell) { cell.parentNode.removeChild(cell); } function getBlockCol(cell) { return Number(cell.id.split(",")[1]); } function getBlockPos(cell) { return Number(cell.id.split(",")[0]); } // Merges the given cell with X amount of cells downward function expandBlock(cell, amount) { cell.setAttribute("rowspan", amount); var pos = getBlockPos(cell); var col = getBlockCol(cell); for (let i = 1; i < amount; i++) { deleteCell(blockArray[pos + i][col]); } }