2

I am using the Gagawa (https://code.google.com/archive/p/gagawa/) library to dynamically create an HTML table to display school courses on a weekly schedule. The problem is that, because I'm using rowspan to increase the size of a cell based on the course's duration, when I try to, for example add a course that meets on MWF, the typical layout for the row would be

<td>...content...</td> <td></td> <td>...content...</td> <td></td> <td>...content...</td>

But, if 2 courses overlap in time but are on different days, inserting the blank <td> element is forced to the right, because <td> for the other course already exists in the next column. See the attached screenshot for more clarification (I've drawn arrows on it in red to show what the correct layout should be; ANT210.101 should be on MWF, but I'm trying to insert a blank <td> where the bottom half of the first ANT220.102 block it, so it gets put to the right of it).

Screenshot

I either need a way to dynamically detect whether or not to put in the blank <td> or a way to make it to that instead of getting shifted right, it gets shifted down (maybe there's a way to do this in CSS?).

Below is my code to dynamically generate the HTML table:

public String generateHTMLScheduleTable(Schedule s){
        Table scheduleTable=new Table();
        scheduleTable.setCSSClass("scheduleTable");
        Tr dayRow=new Tr();
        Th time=new Th(); time.appendText("Time");
        Th mon=new Th(); mon.appendText("Monday");
        Th tue=new Th(); tue.appendText("Tuesday");
        Th wed=new Th(); wed.appendText("Wednesday");
        Th th=new Th(); th.appendText("Thursday");
        Th fri=new Th(); th.appendText("Friday");
        dayRow.appendChild(time, mon, tue, wed, th, fri);       
        TreeMap<Integer, String> colors=mapCoursesToColors(s);

        String[] days={"m", "t", "w", "r", "f"};

        for(int j=8; j<=22; j++){
            int timeInt=j%12;
            if(timeInt==0){
                timeInt=12;
            }
            String timeHr="" + timeInt;

            //System.out.println(timeHr);

            String amPm;
            if(j>11){
                amPm="PM";
            }
            else{
                amPm="AM";
            }
            for(int k=0; k<2; k++){
                String timeMin="";
                if(k==0){
                    timeMin="00";

                }
                else{
                    timeMin="30";
                }
                Tr currRow=new Tr();
                Td currCell=new Td();
                currCell.appendText(timeHr + ":" + timeMin + amPm);
                currRow.appendChild(currCell);

                for(int i=0; i<days.length; i++){
                    Td newCell=new Td();
                    for(Course c : s.getCourses()){
                        if((c.getTime().substring(0, c.getTime().indexOf(':')).equals(timeHr) || c.getTime().substring(0, c.getTime().indexOf(':')).equals("0" + timeHr)) && c.getTime().substring(0, c.getTime().indexOf('-')).contains(timeMin) && c.getTime().substring(0, c.getTime().indexOf('-')).contains(amPm)){
                            if(c.getDays().toLowerCase().contains(days[i])){
                                String currentColor=colors.get(c.getCRN());
                                String timeLastHalf=c.getTime().substring(c.getTime().indexOf('-')+1);
                                int startHr=Integer.parseInt(timeHr);
                                int endHr=Integer.parseInt(timeLastHalf.substring(0, timeLastHalf.indexOf(':')));
                                int numCells=endHr-startHr;
                                numCells=numCells*2;
                                if(!c.getTime().substring(0, c.getTime().indexOf('-')).contains("00")){
                                    if(timeLastHalf.contains("00")){
                                        numCells=numCells-1;
                                    }
                                }
                                else{
                                    if(!timeLastHalf.contains("00")){
                                        numCells=numCells+1;
                                    }
                                }
                                if(numCells<2){
                                    numCells=2;
                                }
                                newCell.setBgcolor(currentColor);
                                newCell.setRowspan("" + numCells);
                                newCell.appendText(c.getTitle());
                                newCell.appendChild(new Br());
                                newCell.appendText(c.getCourseAndSection());
                                newCell.appendChild(new Br());
                                newCell.appendText(c.getTime());
                                Input submit=new Input();
                                submit.setType("submit");
                                submit.setCSSClass("btn");
                                submit.setName("" + c.getCRN());
                                submit.setValue("Remove");
                                Input moreInfo=new Input();
                                moreInfo.setType("submit");
                                moreInfo.setCSSClass("btn");
                                moreInfo.setName(c.getCRN() + "View");
                                moreInfo.setValue("More Info");
                                newCell.appendChild(new Br());
                                newCell.appendChild(submit);
                                newCell.appendChild(moreInfo);
                            }
                        }
                    }
                    currRow.appendChild(newCell);
                }
                scheduleTable.appendChild(currRow);
            }
        }
        String html=scheduleTable.write();
        System.out.println(html);

        return html;
    }
Mat Jones
  • 936
  • 1
  • 10
  • 27

2 Answers2

1

Logic (Asked the OP if its ok he need only pseudocode)

It is wrong approach to check if TD already has a TD to the right of it

Right Approach is to prevent a empty td where there is a rowspan occupation above it so preventing the pushing out of next inserted td. "To simply put always keep the number td always correct"

Your coding is fine all you need to do is add a counter for each day if five counters(because you said that in your example in Q) and then use this counter to walkover occupied space due to above lying rowspan allotment and track it when it ends and only then apply a empty td under that column

Column_count is variable used to track current position of the column inside a row

Next is 5 Overlow indicators which is used to indicated 5 columns and their overflow status.And since you said each row means 30 minutes then your logic for finding if a hour has to be started in a tr is find if the starting time is equal counter of the time associated with each row change causing 30 minute increment

In explanation Overflow_X is used isntead of each individual var name

  1. First of all we need to know before hand how many rows are there gonna be for the outer for loop finding it is left to u
  2. Now with logic First we use switch statement for each day
  3. Now first inside the case we check to see if Overflow_X count is greater than zero this is to understand if there is a need to insert Class details or greater than zero means that it was allocated by above rowspan its default value will be -1.which I am gonna explain why
  4. The default value of overflow variables are set to -1 because each time a rowspan 2 or its multiple depending upon is added a td is added and its value incremented by 2.So in next iteration of for it is checked and if less than zero it does not insert a new td it goes to else case and decrement the value
  5. By this we are bypassing the chance of adding a blank td and causing the pushing of td to the right
  6. So here we only insert a blank td when there is no rowspan allocation above
  7. Overlow_X is checked to see if its zero then its set to -1 as 2n-1 rowspan has been covered

Overflow variables use so during an iteration if it shows that say thursday has Overflow_Th is incremented by 2.So while inserting next row when switch enters case 4 that is for tuesday it checks to see if there was overflow if yes then Overflow_Th is decremented .So here the blank td insertion is avoided which in future will prevent the td from breaking the flow Demo here

td{
  
  border:1px solid black;

}
.pushedOut{
  background:red;
  
}
.bully{
  background:blue;
    color:white
}
<label>Here the value of Overlow_Col2=1(-1+2)</label>
<table>
<tr>
  <td>Data</td>
  <td class="bully " rowspan="2">Pushing</td>
</tr>

<tr>
  <td>Data</td>
 
</tr>
</table>
<label>Here the value of Overlow_Col2=- after decrementing and finding it zero there for resseting to -1 so back to normal but if was no such variable for tracking it then it would have resulted in this following  <span style="color:red">situation</span> </label>
<table>
<tr>
  <td>Data</td>
  <td class="bully " rowspan="2">Pushing</td>
</tr>

<tr>
  <td>Data</td>
   <td class="pushedOut">pushed out becuase of no means of tracking td of previous row</td>
</tr>
</table>

Pseudocode

var column_count=0
Overflow_M=-1,Overflow_Tu=-1,Overflow_W=-1,Overflow_Th=-1,Overflow_Fri=-1

For each number of rows 

for (int column_count=0 ;column_count<5;column_count++)
    {
            switch(column_count){

                  case 0: 
                  if(Overflow_M<0)  {
                         if (content needs to be inserted)
                             {
                             add td and insert content 
                             Overflow_M=Overflow_M+2;
                }else{

                                     Add Blank td

                     }else{

                           Overflow_M=Overflow_M-1;
                           if (Overflow_M==0){
                                     Overflow_M=-1
                                           }

                     }

                  }   

                 case 1: 
                      if(Overflow_Tu<0)  {
                             if (content needs to be inserted)
                                 {
                                 add td and insert content 
                                 Overflow_M=Overflow_M+2;

                              }else{

                                         Add Blank td

                         }else{

                               Overflow_Tu=Overflow_Tu-1;
                                     if (Overflow_M==0){
                                         Overflow_M=-1
                                           }

                         }

                      }  


                     ....
                     ....
                 similarly 2 cases for wed and thurday




  case 4: 
                          if(Overflow_F<0)  {
                                 if (content needs to be inserted)
                                     {
                                     add td and insert content 
                                     Overflow_M=Overflow_M+2;



                                  }else{

                                             Add Blank td

                             }else{

                                   Overflow_F=Overflow_F-1;
                                        if (Overflow_M==0){
                                            Overflow_M=-1
                                           }

                             }

                          } 


                }
         }

If you do not know before hand how many classes are there then you should first iterate through classes and build data base or csv file or json file with data regarding that

td {
  border: 1px solid black;
  width:20%;
}
table,tr{width:100%;}

.pushedOut {
  background: red;
}
.head{
  background:magenta;
}

.bully {
  background: blue;
  color: white
}
<label>Here the value of Overlow_Col2=1(-1+2)</label>
<table>
  <tr class="head">
    <th>Monday</th>
    <th>Tuesday</th>
    <th>Wednesday</th>
    <th>Thursday</th>a
    <th>Friday</th>
  </tr><tr>
    <td>Overlow_M</td>
     <td>Overlow_TU</td>
      <td>Overlow_W</td>
       <td>Overlow_Th</td>
       <td>Overlow_F</td>
       </tr>
 
 
   

  <tr>
   <td class="bully " rowspan="2">Pushing</td>

      <td>Data</td>
    <td class="bully " rowspan="4">Pushing</td>
      <td>Data</td>
       <td>Data</td>
       
         

  </tr>
  
    <tr>
     
    
      <td>Data</td>
       <td>Data</td>
    <td class="bully " rowspan="2">Pushing</td>
  </tr>
      <tr>
     
     <td>Data</td>
      <td>Data</td>

      <td>Data</td>
  </tr>
        <tr>
     
     <td>Data</td>
      <td>Data</td>
    <td>Data</td>
      <td>Data</td>
  </tr>
  <tr class="head">
    <td>Overlow_M</td>
     <td>Overlow_TU</td>
      <td>Overlow_W</td>
       <td>Overlow_Th</td>
       <td>Overlow_F</td>
       </tr>
</table>
Iteration1
Overflow_M Overflow_W with each decrement it is reduced till it becomes zero and upon which it reset to-1 and during next iteration a empty td is put under it and incase of Overflow_W empty td is never put under it  .
In case of Overflow_F td is no put from iteration bumber 2-3 and during iteration number 4 again rows are added to the bottom of it

Javascript Implementation of the logic

 var trcounter = 1;
 var O1 = -1,
   O2 = -1,
   O3 = -1,
   O4 = -1,
   O5 = -1,
   O6 = -1;

 $("#sbt").click(function() {


   var YN = $('#YorN').val();
   //$('#Schedule').append("<td rowspan=" + person + "><p>Cult Anthropology</P</td>");


   if (YN == 'Y' || YN == 'y') {
     var person = prompt("Please enter the rowspan size in multiples of two", "2");
    // alert("y");
   // alert($('#Schedule tr:last td').length);


     /*    if ($('#Schedule tr:last td').length < 6) {

           $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

         } else {

           $('#Schedule').append("<tr> </tr>");
           $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

         }*/





     switch (trcounter) {
       case 1:
         if (O1 < 0) {
      
           if (trcounter < 7) {

             $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

           } else {
             $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');
           }
           O1 = O1 + parseInt(person);
          // alert(O1);
         } else {
            alert("This TimeSlot on Monday is occupied");
           O1 = O1 - 1;
           if (O1 == 0) {
             O1 = -1;
           }
         }
         break;

       case 2:
         if (O2 < 0) {
      
           if (trcounter < 7) {

             $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

           } else {
             $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');
           }
           O2 = O2 + parseInt(person);
           //alert(O1);
         } else {
           alert("This TimeSlot on Tuesday is occupied");
           O2 = O2 - 1;
           if (O2 == 0) {
             O2 = -1;
           }
         }
         break;
       case 3:
          if (O3 < 0) {
      
           if (trcounter < 7) {

             $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

           } else {
             $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');
           }
           O3 = O3 + parseInt(person);
         //  alert(O1);
         } else {
           alert("This TimeSlot on Wednesday is occupied");
           O3 = O3 - 1;
           if (O3 == 0) {
             O3 = -1;
           }
         }
         break;
       case 4:
           if (O4 < 0) {
      
           if (trcounter < 7) {

             $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

           } else {
             $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');
           }
           O4 = O4 + parseInt(person);
         //  alert(O1);
         } else {
           alert("This TimeSlot on Wednesday is occupied");
           O4 = O4 - 1;
           if (O4 == 0) {
             O4 = -1;
           }
         }
         break;
       case 5:
         if (O5 < 0) {
      
           if (trcounter < 7) {

             $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

           } else {
             $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');
           }
           O5 = O5 + parseInt(person);
         //  alert(O1);
         } else {
           alert("This TimeSlot on Wednesday is occupied");
           O5 = O5 - 1;
           if (O5 == 0) {
             O5 = -1;
           }
         }
         break;
       case 6:
         if (O6 < 0) {
      
           if (trcounter < 7) {

             $('#Schedule tr:last ').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');

           } else {
             $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append('<td class="red" rowspan="' + person + '"><p>Cult Anthropology</P</td>');
           }
           O6 = O6 + parseInt(person);
          // alert(O1);
         } else {
           alert("This TimeSlot on Wednesday is occupied");
           O6 = O6 - 1;
           if (O6 == 0) {
             O6 = -1;
           }
         }
         break;

     }
     if (trcounter == 7) {
       trcounter = 1;
        $('#Schedule').append("<tr> </tr>");
       $('#Status').html("REACHED SATURDAY MOVING ON TO NEXT TIME SLOT");
     } else {
       trcounter++;

     }
   } else if(YN == 'N' || YN == 'n') {


     /* if (O1 > 0)) {
       O1--;
     } else if (O1 == 0) {
       O1 = -1;
     }
     if ($('#Schedule tr:last td').length < 6) {

       $('#Schedule tr:last ').append("<td ></td>");

     } else {
       $('#Schedule').append("<tr> </tr>");
       $('#Schedule tr:last').append("<td ></td>");
     }*/
     switch (trcounter) {
       case 1:
        //  alert("trcounter"+trcounter+"O1"+O1);
         if (O1 < 0) {
           if (trcounter < 7) {

             $('#Schedule tr:last ').append("<td ></td>");

           } else {
           //  $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append("<td ></td>");
           }
          
         } else {
           O1 = O1 - 1;
          // alert(O1);
           if (O1 == 0) {
             O1 = -1;
           }
             $('#Status').html("Empty Node Cannot be inserted here becuase previous rowspan allocation is taking up the space");
         }
         break;
   
       case 2:
         if (O2 < 0) {
           if (trcounter < 7) {

             $('#Schedule tr:last ').append("<td ></td>");

           } else {
           //  $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append("<td ></td>");
           }
          
         } else {
           O2 = O2 - 1;
          // alert(O1);
           if (O2 == 0) {
             O2 = -1;
           }
                        $('#Status').html("Empty Node Cannot be inserted here becuase previous rowspan allocation is taking up the space");
         }
         break;
       case 3:
         if (O3 < 0) {
           if (trcounter < 7) {

             $('#Schedule tr:last ').append("<td ></td>");

           } else {
           //  $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append("<td ></td>");
           }
          
         } else {
           O3 = O3 - 1;
          // alert(O1);
           if (O3 == 0) {
             O3 = -1;
           }
                      $('#Status').html("Empty Node Cannot be inserted here becuase previous rowspan allocation is taking up the space");
         }
         break;
       case 4:
        if (O4 < 0) {
           if (trcounter < 7) {

             $('#Schedule tr:last ').append("<td ></td>");

           } else {
           //  $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append("<td ></td>");
           }
          
         } else {
           O4 = O4 - 1;
          // alert(O1);
           if (O4 == 0) {
             O4 = -1;
           }
                        $('#Status').html("Empty Node Cannot be inserted here becuase previous rowspan allocation is taking up the space");
         }
         break;
       case 5:
         if (O5 < 0) {
           if (trcounter < 7) {

             $('#Schedule tr:last ').append("<td ></td>");

           } else {
           //  $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append("<td ></td>");
           }
          
         } else {
           O5 = O5 - 1;
          // alert(O1);
           if (O5 == 0) {
             O5 = -1;
           }
                          $('#Status').html("Empty Node Cannot be inserted here becuase previous rowspan allocation is taking up the space");
         }
         break;
       case 6:
         if (O6 < 0) {
           if (trcounter < 7) {

             $('#Schedule tr:last ').append("<td ></td>");

           } else {
           //  $('#Schedule').append("<tr> </tr>");
             $('#Schedule tr:last').append("<td ></td>");
           }
          
         } else {
           O6 = O6 - 1;
          // alert(O1);
           if (O6 == 0) {
             O6 = -1;
           }
                       $('#Status').html("Empty Node Cannot be inserted here becuase previous rowspan allocation is taking up the space");
         }
         break;

     }
     if (trcounter == 7) {
       trcounter = 1;
        $('#Schedule').append("<tr> </tr>");
       $('#Status').html("REACHED SATURDAY MOVING ON TO NEXT TIME SLOT");
     } else {
       trcounter++;
     }


   }else{
    alert("Either Enter Y or N (Y-->Allocate td with class N--> Go to Next day)");
   }


 });
.red {
  background: red;
}
table{border:1px black solid;width:100%;}
td{width:16.66%;
max-width:16.66%;
height:50px;
}
#Status{
  
  Color:cyan;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<p>
  This is a dummy showing how to avoid butted out tds so for adding a rows span enter y else n and click proceed

</p>
<p id="Status">

</p>
<input id="YorN" type="text" />
<input type="button" id="sbt" value="Proceed  " />
<table>
<tr>
    <td>
      Monday</td>
    <td>
      Tuesday</td>
    <td>
      Wednesday</td>
    <td>
      Thursday</td>
    <td>
      Friday</td>
    <td>
      Saturday</td>
  </tr>

</table>
</table>
<table id="Schedule">
  <tr></tr>
</table>
codefreaK
  • 3,584
  • 5
  • 34
  • 65
  • is it supposed to be overflow_M for all the cases, or should it go through overflow_M to overflow_F? – Mat Jones May 01 '16 at 22:21
  • Each variable with your own liking for each day or td to track .I hope you got the logic .It simply tracks who many tds should be omitted for each rowspan allocation I have added html example so you get the idea why its being pushed out. – codefreaK May 02 '16 at 11:33
  • I still haven't been able to get it to work. Could you make your pseudocode a little more inclusive/complete? Which loop does it go within? Do I need to change the nesting order of the loops? – Mat Jones May 02 '16 at 15:46
  • Okay can you post your entire code to paste bin or something and sent the link here (the one with what I asked you to change)and can you tell me another thing about the first and second loops from outside the one with 8-22 and am pm and in what format schedule is passed onto this – codefreaK May 02 '16 at 16:41
  • Will it okay if I show you this logic using javascript only where you can enter the data using a live example – codefreaK May 02 '16 at 16:59
  • I figured it out using a different approach entirely. Thank you anyway. – Mat Jones May 02 '16 at 19:12
  • and what did you do ?? – codefreaK May 02 '16 at 19:45
  • It was getting to be a bit of spaghetti code so I changed my implementation entirely. I create a 2 dimensional array of objects and treat the table as a coordinate system. If a course begins in that coordinate, I put the Td element there, and below it (based on the rowspan) I put the string "filled", and everywhere else remains null. Then I loop through each coordinate and if the value is an instance of Td then I add the Td to the row, and if it is null then I add a blank Td. – Mat Jones May 02 '16 at 19:48
  • Have you checked out my working example .And logically they are both same mine use simple if checks and overflow flags you use multiple loop for traversing row and column .But here also the same problem can arise what did you do when there was a multiple rowspan allocation and insertion on the same column next row. and thanks bro for the points my only regret is I couldnt explain what I was saying in a better way – codefreaK May 02 '16 at 19:56
  • I check the value of that coordinate in the coordinate matrix. Other parts of the code will not allow you to add courses that conflict with each other, so if the value of the coordinate is not null, I skip over it without adding the empty Td. – Mat Jones May 02 '16 at 19:58
  • yes that was what I was talking all along not to insert the td if there is a rowspan allocation there for it I used overflow flags you used to compare if there two courses collided in timeslots.Did you understand about td from my answer or you came up with your own ?Anyway what you did was nice its better to seperate logic from presentation rather than depend on td its better to compare time slots – codefreaK May 02 '16 at 20:00
  • I found your solution rather confusing, and I figured my new solution out with a friend of mine earlier today. – Mat Jones May 02 '16 at 20:05
  • Ok bro My first sentence in answer is this " Right Approach is to prevent a empty td where there is a rowspan allocation ".And finally even with your method it is this what you did :).Anyway my only regret is that I couldnt be more clearer – codefreaK May 02 '16 at 20:09
-1

I don't think if I really understand your question but here's my suggestion:

Please see HTML DOM Parser

You can choose which to use from these suggested codes. Insert it/them in your code where you think it should be placed, it can be after the display of table or during.

Search for a single/set or set of elements and an object/array will be returned.

$td = $html->find("td", 0);

if (is_object($td)) {
    //code here
}

Same as above but in different way.

if($html->find("td", 0)) {
    //code here
}else{
    //code here
}

Or you can also look at this foreach method given here.

Community
  • 1
  • 1
rhavendc
  • 985
  • 8
  • 21