Jump to content

Unexpected behaviour while looping a table


Go to solution Solved by Barand,

Recommended Posts

Hi Freaks, the weekend is upon us again. I wish you all well. I have an issue I've been working on today and have hit a mental roadblock. Hoping someone with the time and will will talk me through it.

I'm creating a table while looping through an API array and I've hit a couple snags. Here is the repeated HTML ->

$html = "
    <tr class='mt-2'>
        <td>{$rank}.</td>
        <td><img src='{$image}' height='75' width='75'></td>
        <td>{$name}</td>
        <td class='bold'>\${$final_worth}B</td>
        <td class='{$class}'>\${$last_change}</td>
        <td>{$country}</td>
        <td>{$source}</td>
        <td><button class='bg-color-primary text-color-third px-2' id='more_btn' onclick='showDetails({$cnt})'>More</button></td>
    </tr>
    <tr >
        <div id='details'>lorem fucking ipsum wahoo baby</div>
    </tr>

    ";

Everything was going as expected until I went to add the second row (div#details).

There's actually 2 issues at play here - the first is how I make each button/div#details connected so button1 only effects div1 etc.

I can't tackle that one yet though, because right now when any button is clicked div#details shows up above the table header rather than underneath the previous row.

So until I have the positioning correct I can't really tackle the js functionality. Can someone please tell me why the <tr><div#details> is not appearing underneath it's previous row? The js code is as follows ->

<script>
  var cnt = <?php echo $cnt; ?>;
  function showDetails(cnt) {
      var details = "details";
      var x = document.getElementById(details);
      if (x.style.display === "none") {
          x.style.display = "block";
      } else {
          x.style.display = "none";
      }
  }
    
</script>

I know the code is a mess right now. It's kind of shameful lol but like I said I can't really do more with it until I can figure out why that table row isn't positioning properly

6 minutes ago, TechnoDiver said:
    <tr >
        <div id='details'>lorem fucking ipsum wahoo baby</div>
    </tr>

try changing that to

   <tr >
        <td colspan='8' id='details'>lorem fucking ipsum wahoo baby</td>
    </tr>

If it ain't in a cell, it's rejected from the table, which is why it appears above.

11 minutes ago, Barand said:

try changing that to

   <tr >
        <td colspan='8' id='details'>lorem fucking ipsum wahoo baby</td>
    </tr>

If it ain't in a cell, it's rejected from the table, which is why it appears above.

I was actually just working on exactly this. I had a revelation as I was leaving the site from my OP. What I'm actually working on is that it's not working and I don't know why ->

$html = "
  <tr class='mt-2'>
      <td>{$rank}.</td>
      <td><img src='{$image}' height='75' width='75'></td>
      <td>{$name}</td>
      <td class='bold'>\${$final_worth}B</td>
      <td class='{$class}'>\${$last_change}</td>
      <td>{$country}</td>
      <td>{$source}</td>
      <td><button class='bg-color-primary text-color-third px-2' id='more_btn' onclick='showDetails({$cnt})'>More</button></td>
  </tr>
  <tr >
      <td colspan='8' id='details{$cnt}' style='display: none'>lorem fucking ipsum wahoo baby - {$cnt}</td>
  </tr>

  ";

but even with the colspan it's only populating it into the first column.

On the brighter side, I got the js functionality working lol

but for some reason it's not spanning the 8 columns. Any ideas??

How do you know with the display: none ?

If I supply some dummy values, remove the display:none and add borders to the table so I can see what's happening...

$rank = $image = $name = $final_worth = $country = $source = $cnt = $class = $last_change = 'X';

$html = "
  <tr class='mt-2'>
      <td>{$rank}.</td>
      <td><img src='{$image}' height='75' width='75'></td>
      <td>{$name}</td>
      <td class='bold'>\${$final_worth}B</td>
      <td class='{$class}'>\${$last_change}</td>
      <td>{$country}</td>
      <td>{$source}</td>
      <td><button class='bg-color-primary text-color-third px-2' id='more_btn' onclick='showDetails({$cnt})'>More</button></td>
  </tr>
  <tr >
      <td colspan='8' id='details{$cnt}' >lorem fucking ipsum wahoo baby - {$cnt}</td>
  </tr>

  ";

I see

image.png.26d6c2247ac61308205a7ad183ebdbe0.png

9 minutes ago, Barand said:

How do you know with the display: none ?

ok, I was talking about after I hit the button, in the script that changes it to block instead of none.

funnily enough, when I take it out it displays properly (colspan=8)

So, if I take out display: none the second row spans the 8 cols. BUT they're visible on page load and I don't want that.

When I have display: none there they obviously don't appear on page load and they DO appear after I hit the button, except when they do appear it pushes everything from the top row over and only populates the first col

freaks_question_ss.png.18cc034e962651421fa80fea28116dd5.png

as in the SS above. Why is this? here's the js again for reference ->

<script>
        
function showDetails(cnt) {
  var details = "details"+cnt;
  var x = document.getElementById(details);
  if (x.style.display === "none") {
      x.style.display = "block";
  } else {
      x.style.display = "none";
  }
}
</script>

I can't get my head around why this is happening.

9 minutes ago, Barand said:

If I put the style='display: none' back, I get

what happens when you hit the button?

Here's my entire table element ->

<table class="col-lg-12 mb-5">
  <tr class="bg-color-fourth mb-2">
      <th class="ps-1">Rank</th>
      <th></th>
      <th>Name</th>
      <th>Total net worth</th>
      <th>Last change</th>
      <th>Country</th>
      <th>Industry</th>
      <th></th>
  </tr>

  <?php 
      $cnt = 0;
      while($cnt<10) {
          $leech = $leeches[$cnt];
          $name = $leech->personName;
          $image = explode("//", $leech->squareImage);
          $image[0] = "https://";
          $image = implode("", $image);
          $age = "?";
          $final_worth = (int)($leech->finalWorth/1000);
          $last_change = (int)($leech->finalWorth - $leech->estWorthPrev)/1000;
          if($leech->estWorthPrev > $leech->finalWorth) {
              $class = "red";
          } elseif($leech->estWorthPrev == $leech->finalWorth) {
              $class = "black";
          } else {
              $class = "green";
          }
          $source = $leech->source;
          $country = $leech->countryOfCitizenship;

          $source = ucwords($leech->source);
          $rank = $cnt + 1;
          $html = "
              <tr class='mt-2'>
                  <td>{$rank}.</td>
                  <td><img src='{$image}' height='75' width='75'></td>
                  <td>{$name}</td>
                  <td class='bold'>\${$final_worth}B</td>
                  <td class='{$class}'>\${$last_change}</td>
                  <td>{$country}</td>
                  <td>{$source}</td>
                  <td><button class='bg-color-primary text-color-third px-2' id='more_btn' onclick='showDetails({$cnt})'>More &nbsp;<i class='fa fa-arrows-v' aria-hidden='true'></i></button>
                  </td>
              </tr>
              <tr >
                  <td colspan='8' id='details{$cnt}' style='display: none'>lorem fucking ipsum wahoo baby - {$cnt}</td>
              </tr>

              ";
          $cnt++;
          echo $html; 
      }     
  ?>
 </table>

It uses no css other than that inline style and adding some color to positive/negative values. I have no idea what could cause it like this.

Have you tried to use the JS to see what happens for you after you click the button??

  • Solution

Instead of changing the display to "block" when you click the button, set it to "display: table-cell;"

<script type="text/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type='text/javascript'>
    function showDetails(cnt) {
        
        $(".more").css("display", "none");            // hide all
        
        var details = "details"+cnt;
        var x = document.getElementById(details);
        if (x.style.display === "none") {
          x.style.display = "table-cell";             // display requested one
        } else {
          x.style.display = "none";
        }
    }


</script>

 

Edited by Barand
  • Great Answer 1

FYI

If you have a div inside the 8-col td, then it works with display:block

  <tr >
      <td colspan='8'> 
          <div class='more' id='details{$cnt}' >lorem fucking ipsum wahoo baby - {$cnt}</div>
      </td>
  </tr>

 

For future reference, rather changing the value of display directly like that, it's easier to just add/remove a class which will apply display: none;

Doing it that way, you don't have to worry about whether it should be 'block', 'inline', 'table-cell', 'grid', etc.  You just apply display: none; with a class to hide it, then remove the class so display: none; gets removed and it falls back to whatever the previous value was.

 

  • Like 1
This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.