I'm building a calendar scheduler where I am hoping to add multiple tasks to one employee row. Whenever I try to add multiple tasks to the same time span, the spans no longer line up. Here is an example of how it looks now: . What would be the best practice to add tasks to the same day columns while keeping a task like "Slaughter them" similar?
HTML Script:
<script> var sysDate = new Date(); var sysDay = new Date(); var sysMonth = new Date(); var dayCount = sysDay.getDay(); var weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; let employee; let typeofKey; let empArry = []; let x = 1; let y = 0; let trInc= 0; var drawTable = '<table id = wholeTable>'; drawTable += "<thead>"; drawTable += "<tr>"; drawTable += "<th style='color:white;'>Employee Name<\/th>"; let today = new Date(); let dd = today.getDate(); let mm = today.getMonth()+1; //January is 0! let mmN = mm; let yyyy = today.getFullYear(); let oneWeekAhead = new Date(); let nextWeek = (today.getDate()+10) + 10; /* If next week falls into the next month, print correctly */ if (nextWeek > 30 && (mmN == 9 || mmN == 4 || mmN == 6 || mmN == 11)) { mmN++; nextWeek -= 30; } else if (nextWeek > 31 && (mmN == 1 || mmN == 3 || mmN == 5 || mmN == 7 || mmN == 8 || mmN == 10 || mmN == 12)) { mmN++; nextWeek -= 31; } else if (nextWeek > 28 && mmN == 2) { mmN++; nextWeek -= 28; } /* Formatting of the dates at the top of the table */ if(dd < 10) { dd = '0'+ dd; } if(nextWeek < 10) { nextWeek = '0' + nextWeek; } if(mmN < 10) { mmN = '0' + mmN } if(mm < 10) { mm = '0' + mm; } let edate = yyyy + mmN + nextWeek; /* Finds the logged earliest and latest dates */ let startDate1 = yyyy.toString() + mm.toString() + dd.toString(); let startDate = parseInt(startDate1); let endDate = parseInt(edate); let startDateN = 20180501; let endDateN = 20180531; /* Change the strings of dates to ints for calculation of start and end date of the table */ if( localStorage.length > 0){ for (var key in localStorage) { typeofKey = (typeof localStorage[key]); if (typeofKey == 'string' || typeofKey instanceof String ){ emp1 = JSON.parse(localStorage.getItem(key)); if ("Task" in emp1) { for (let i = 0; i < emp1.Task.length; i++) { startDateN = parseInt(emp1.Task[i]['Task Start Date'].substr(0,4) + emp1.Task[i]['Task Start Date'].substr(5,2) + emp1.Task[i]['Task Start Date'].substr(8,2)); endDateN = parseInt(emp1.Task[i]['Task End Date'].substr(0,4) + emp1.Task[i]['Task End Date'].substr(5,2) + emp1.Task[i]['Task End Date'].substr(8,2)); if(endDateN > endDate) { endDate = endDateN; } if(startDateN < startDate) { startDate = startDateN; } } } } } } let numStr = null; let numStrDay = null; let finalDay = null; let finalDayF = null; let colCount = 0; /* Correctly print the months and days at the top of the table */ for (let i = startDate; i <= endDate +1; i++) { numStr = (i.toString()).substr(4,2); numStrDay = (i.toString()).substr(6,2); if(numStr == '09' || numStr == '04' || numStr == '06' || numStr == '11') { if(numStrDay == '31') { i += 69; } else { finalDay = i.toString() finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2)); drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>"; colCount++; } } else if(numStr == '01' || numStr == '03' || numStr == '05' || numStr == '07' || numStr == '08' || numStr == '10' || numStr == '12') { if(numStrDay == '32') { i += 68; } else { finalDay = i.toString() finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2)); drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>"; colCount++; } } else if(numStr == '02') { if(numStrDay == '29') { i += 71; } else { finalDay = i.toString() finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2)); drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>"; colCount++; } } else { finalDay = i.toString() finalDayF = (finalDay.substr(0,4)) + "-" + (finalDay.substr(4,2)) + "-" + (finalDay.substr(6,2)); drawTable += "<th class = days id = days" + x + '-' + y + ">" + finalDayF + "</th>"; colCount++; } x++; } drawTable += "</tr>"; drawTable += "</thead>"; drawTable += '<tbody class="dragscroll">'; //drawTable += "<tr id =" + trInc + ">"; //trInc++; //counters for the employee and date rows/col x=0; y=1; // counter for the main table let z =1; for (var key in localStorage) { typeofKey = (typeof localStorage[key]); //cols of the employee names if(typeofKey == 'string' || typeofKey instanceof String ){ drawTable += "<tr id =" + trInc + ">"; trInc++; employee = JSON.parse(localStorage.getItem(key)); drawTable += "<td class = employ id =emp" + x + '-' + y + ">" + employee['Employee Name'] + "</td>"; // rows and cols of the main table and date for (let j = 0; j < colCount; j++) { drawTable += "<td class =" + z + '-' + y + "></td>"; z++; } // set z to one to start the main tables x at 1 for off by one error z=1; //reset x for each row x=0; drawTable += '</tr>'; y++; } } drawTable += '<tr>'; var noRows = 14 - localStorage.length; for(; noRows >= 0; noRows--){ drawTable += "<td class = employ id =emp" + x + '-' + y + ">" + "" + "</td>"; // rows and cols of the main table and date for (let j = 0; j < colCount; j++) { drawTable += "<td class =" + z + '-' + y + "></td>"; z++; } // set z to one to start the main tables x at 1 for off by one error z=1; //reset x for each row x=0; drawTable += '</tr>'; y++; } drawTable += "</tbody>"; drawTable += "</table>"; document.write(drawTable); </script>
CSS:
table { /* border: 0.0625em solid black; */ table-layout: fixed; position: relative; width: auto; overflow: hidden; border-collapse: collapse; box-shadow: 0 0 20px rgba(0,0,0,0.1); } html, body{ height: 100%; width: 100%; background: linear-gradient(45deg, #e1e1e1, #f6f6f6); } /*thead*/ thead { position: relative; display: block; /*seperates the header from the body allowing it to be positioned*/ width: 1535px; overflow: visible; /* border: 1px solid black; */ } td, th { padding: 0.75em 1.5em; text-align: left; } thead th { min-width: 140px; max-width: 140px; height: 35px; text-align: center; } thead th:nth-child(1) { /*first cell in the header*/ position: relative; display: float; min-width: 140px; background-color: #202020; } /*tbody*/ tbody { position: relative; display: block; /*seperates the tbody from the header*/ width: 1535px; height: 475px; overflow: scroll; } tbody td { background-color: white; min-width: 140px; max-width: 140px; border: 2px solid #474747; white-space: nowrap; } tbody tr td:nth-child(1) { /*the first cell in each tr*/ position: relative; /*display: block; seperates the first column from the tbody*/ height: 40px; min-width: 140px; max-width: 140px; } .dragscroll { overflow-y: hidden; margin-right: 0; height: 600px; } .days { background-color: #31bc86; color: white; text-align: center; } .employ { background-color: #2ea879; color: white; text-align: center; } #taskDiv { position: absolute; border: 2px solid black; } #days, #emp{ background-color: #071833; color: white; } ::-webkit-scrollbar { width: 20px; } /* Track */ ::-webkit-scrollbar-track { box-shadow: inset 0 0 5px black; } /* Handle */ ::-webkit-scrollbar-thumb { background: #071833; } /* Handle on hover */ ::-webkit-scrollbar-thumb:hover { background: #1caf8f }
JS:
function getRandomColor() { var letters = '0123456789ABCDEF'; var color = '#'; for (var i = 0; i < 6; i++) { color += letters[Math.floor(Math.random() * 16)]; } return color; } $(document).ready(function(){ let typeofKey; let empArry = []; let employee; let myTable = document.getElementById('wholeTable'); let colFill = false; let color = null; //cols of the employee names for (var i = 0; i < localStorage.length; i++){ empArry.push(localStorage.key(i)) } // loop through the local storage and pull the data for(let j = 0; j < empArry.length; j++){ color = getRandomColor(); employee = JSON.parse(localStorage.getItem(empArry[j])); // If employee has any task if("Task" in employee){ // while employee has task in his array for(let taskIndex = 0; taskIndex < employee.Task.length; taskIndex++){ for(let k = 1; k < myTable.rows[0].cells.length; k++) { if(myTable.rows[0].cells[k].innerHTML == employee.Task[taskIndex]["Task Start Date"]) { colFill = true; } if(colFill == true) { myTable.rows[j+1].cells[k].innerHTML += '<div style="background-color:' + color + '">' + employee.Task[taskIndex]["Task Name"] + '</br></div>'; } if(myTable.rows[0].cells[k].innerHTML == employee.Task[taskIndex]["Task End Date"]) { colFill = false; } } } } } });
JSFiddle: https://jsfiddle.net/py5gzw0b/1/#&togetherjs=eM8xgAd5eV
4 Answers
Answers 1
Set the vertical-align CSS property for those table cells to top;
td { vertical-align:top; }
https://developer.mozilla.org/en-US/docs/Web/CSS/vertical-align
Answers 2
If you need each item to be on its own row [along with all identical tasks] and perfectly aligned there, then you would need to create row 1, and insert only the Slaughter tasks, followed by creating row 2, inserting only the Cry tasks. This would then ensure that they would all correctly line up with one another, although it would take up more space as a result.
Answers 3
Another solution besides creating a row for each task would be to use jQuery to find the "max top of the task" and setting all instances at that top. Since they take the same space it should be doable and more flexible BUT you're in for some css-positioning fun.
To be more specific, you should :
1/ Add an unique identifier to each task : <div id_task="1" style=...
2/ Loop on each instance to find max top value :
maxTop=0; $('[id_task=1]').each(function(){ newTop=$(this).position().top; if(newTop>maxTop)maxTop=newTop; });
3/ Use maxTop
to set all id_task=1
to the same top, probably set these divs to relative too : $('[id_task=1]').css({'top':maxTop,'position':'relative');
4/ Enjoy fine-tuning this to close in on your desired goal, it'll take a while ^^
I made the code quickly as an example, there's no guarantee to it.
Answers 4
Take a look at this:
var cols = ['Mon','Tue','Wed','Thu','Fri','Sat','Sun'] var employees = [ { Name: 'Jason', Task:[ {'Task Start Date':'Mon','Task End Date':'Thu','Task Name':'Do nothing'}, {'Task Start Date':'Thu','Task End Date':'Fri','Task Name':'Do a bit'}, {'Task Start Date':'Sat','Task End Date':'Sun','Task Name':'Do everything'} ] }, { Name: 'Timmy', Task:[ {'Task Start Date':'Mon','Task End Date':'Sun','Task Name':'On vacation'}, {'Task Start Date':'Sat','Task End Date':'Sun','Task Name':'Still on vacation'}, ] } ] function RowCompound(employee,columns){ var tasks = employee.Task var spans = [] var max_rows = 1 var rowmap = [] var rows = [] function calcSpans(){ for(var i=0;i<tasks.length;i++){ var cspan = null for(var u=0;u<columns.length;u++){ if(tasks[i]['Task Start Date']==columns[u]){ cspan = {row:0,start:u,task:tasks[i]} } if(cspan && tasks[i]['Task End Date']==columns[u]){ cspan.end = u spans.push(cspan) cspan = null } } if(cspan){ cspan.end = columns.length-1 spans.push(cspan) } } } function solveConflicts(){ var conflict = true while(conflict){ conflict = false for(var i=0;i<spans.length;i++){ for(var u=i+1;u<spans.length;u++){ if(spans[i].row!=spans[u].row) continue if(spans[i].start>spans[u].end || spans[i].end<spans[u].start) continue conflict = true max_rows = Math.max(max_rows,++spans[u].row + 1) } } } } function createRowMap(){ for(var u=0;u<max_rows;u++){ var row = [] for(var i=0;i<columns.length;i++){ var empty = true for(var k=0;k<spans.length;k++){ if(spans[k].row!=u) continue if(i==spans[k].start){ empty = false var span = spans[k].end-spans[k].start+1 row.push({task:spans[k].task,colspan:span,rowspan:1}) i += span-1 break } } if(empty) row.push({task:null,colspan:1,rowspan:1}) } rowmap.push(row) } } function buildDom(){ for(var i=0;i<rowmap.length;i++){ var row = document.createElement('tr') for(var u=0;u<rowmap[i].length;u++){ if(rowmap[i][u].rowspan==0) continue var cell = document.createElement('td') cell.colSpan = rowmap[i][u].colspan cell.rowSpan = rowmap[i][u].rowspan if(rowmap[i][u].task){ cell.innerHTML = rowmap[i][u].task['Task Name'] cell.className = 'busy' } row.appendChild(cell) } rows.push(row) } var head = document.createElement('td') head.rowSpan = max_rows head.innerHTML = employee.Name rows[0].prepend(head) } calcSpans() solveConflicts() createRowMap() buildDom() return rows } // example use employees.forEach(function (emp){ var result_rows = RowCompound(emp,cols) for(var i in result_rows){ document.getElementById('table').appendChild(result_rows[i]) } })
table{ width: 100%; border-collapse: collapse; } table td{ border: solid 1px #ccc; width: 50px; } table td.busy{ background-color: dodgerblue; color: white; }
<table id="table"> <thead> <th>Employee</th> <th>Mon</th> <th>Tue</th> <th>Wed</th> <th>Thu</th> <th>Fri</th> <th>Sat</th> <th>Sun</th> </thead> </table>
What this does is:
- Create virtual spans for each task
- If the spans overlap, push them one row lower
- Create multiple rows utilizing the
rowSpan
attribute - Append the said rows to the table
You're gonna need to rewrite your code a little for this to work, but i think its the way to go. Please note, the createRowCompound
function requires the columns of the table as array in order to create the layout. See the example use.
Questions?
0 comments:
Post a Comment