Thursday, May 31, 2018

Add multiple colspans that line up in HTML

Leave a Comment

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: Calendar as of 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?

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment