Search code examples
jquerycssjquery-uioverflowjquery-ui-selectable

Having jQuery UI Selectable both as grid and a list in a table


I have prepared a jsFiddle for my question -

screenshot

I am trying to have jQuery UI Selectable in a table with yellow header and footer rows. Once as a grid of numbers in the left cell and then as a list of letters in the right cell.

Also I am trying to have the table occupy both 100% of browser width and height.

That is why I have assigned CSS-properties width: 100% and height: 100vh to the table and overflow-y: scroll to the both selectables.

For some reason however the right scroll is not working, i.e. the whole list of letters is displayed and thus blows up the table height.

TLDR:

  • Numbers/Letters lists should have same height and be scrollable
  • Yellow header/footer should be visible at top/bottom of browser window

Here is my code -

Javascript:

  $(function() {
    $("#selectable1").selectable();
    $("#selectable2").selectable();
  });

CSS:

<table>
  <tr>
    <td colspan=2 bgcolor="yellow">Header1</td>
  </tr>
  <tr>
    <td>
      <ol id="selectable1">
        <li class="ui-state-default">1</li>
        <li class="ui-state-default">2</li>
        <li class="ui-state-default">3</li>
        <li class="ui-state-default">4</li>
        <li class="ui-state-default">5</li>
        <li class="ui-state-default">6</li>
        <li class="ui-state-default">7</li>
        <li class="ui-state-default">8</li>
        <li class="ui-state-default">9</li>
        <li class="ui-state-default">10</li>
        <li class="ui-state-default">11</li>
        <li class="ui-state-default">12</li>
      </ol>
    </td>
    <td>
      <ol id="selectable2">
        <li class="ui-state-default">A</li>
        <li class="ui-state-default">B</li>
        <li class="ui-state-default">C</li>
        <li class="ui-state-default">D</li>
        <li class="ui-state-default">E</li>
        <li class="ui-state-default">F</li>
        <li class="ui-state-default">G</li>
        <li class="ui-state-default">H</li>
        <li class="ui-state-default">I</li>
        <li class="ui-state-default">J</li>
      </ol>
    </td>
  </tr>
  <tr>
    <td colspan=2 bgcolor="yellow">Footer1</td>
  </tr>
</table>

CSS:

table {
  width: 100%;
  height: 100vh;
}

#selectable1 {
  list-style-type: none;
  margin: 0;
  padding: 0;
  overflow-y: scroll;
}

#selectable2 {
  list-style-type: none;
  margin: 0;
  padding: 0;
  width: 100px;
  overflow-y: scroll; /* WHY IS THIS NOT WORKING? */
}

#selectable1 li,
#selectable2 li {
  margin: 3px;
  padding: 1px;
  float: left;
  width: 100px;
  height: 80px;
  font-size: 4em;
  text-align: center;
}

The background for my question is that I am trying to create a card game with playing tables on the left and list of players in the lobby on the right -

game screenshot


Solution

  • Update:

    To support IE 11, you can update your CSS to include -ms-grid specific styles and it should work but again you might have to test it thoroughly:

    $(function() {
      $("#selectable1").selectable();
      $("#selectable2").selectable();
    });
    body {
      margin: 0;
      padding: 0;
    }
    
    .header {
      background: yellow;
      -ms-grid-row: 1; /* for IE */
    }
    
    .footer {
      background: yellow;
      -ms-grid-row: 3; /* for IE */
    }
    
    div.table {
      display: grid;
      width: 100vw;
      height: 100vh;
      
      /* for IE */
      display: -ms-grid;
      -ms-grid-columns: 1fr;
      -ms-grid-rows: 20px 1fr 20px;
    }
    
    div.container {
      display: grid;
      grid-template-columns: auto 140px;
      grid-column-gap: 10px;
      overflow: hidden;
      
      /* for IE */
      display: -ms-grid;
      -ms-grid-columns: 1fr 140px;
      -ms-grid-rows: 1fr;
      -ms-grid-row: 2;
    }
    
    div.container div {
      overflow: auto;
    }
    
    div.container div.column1 {
        -ms-grid-column: 1; /* for IE */
    }
    
    div.container div.column2 {
        -ms-grid-column: 2; /* for IE */
    }
    
    #selectable1 {
      list-style-type: none;
      margin: 0;
      padding: 0;
      flex: 1;
    }
    
    #selectable2 {
      list-style-type: none;
      margin: 0;
      padding: 0;
    }
    
    #selectable1 li,
    #selectable2 li {
      margin: 3px;
      padding: 1px;
      float: left;
      width: 100px;
      height: 80px;
      font-size: 4em;
      text-align: center;
    }
    <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <div class="table">
      <div class="header">Header1</div>
      <div class="container">
        <div class="column1">
          <ol id="selectable1">
            <li class="ui-state-default">1</li>
            <li class="ui-state-default">2</li>
            <li class="ui-state-default">3</li>
            <li class="ui-state-default">4</li>
            <li class="ui-state-default">5</li>
            <li class="ui-state-default">6</li>
            <li class="ui-state-default">7</li>
            <li class="ui-state-default">8</li>
            <li class="ui-state-default">9</li>
            <li class="ui-state-default">10</li>
            <li class="ui-state-default">11</li>
            <li class="ui-state-default">12</li>
          </ol>
        </div>
        <div class="column2">
          <ol id="selectable2">
            <li class="ui-state-default">A</li>
            <li class="ui-state-default">B</li>
            <li class="ui-state-default">C</li>
            <li class="ui-state-default">D</li>
            <li class="ui-state-default">E</li>
            <li class="ui-state-default">F</li>
            <li class="ui-state-default">G</li>
            <li class="ui-state-default">H</li>
            <li class="ui-state-default">I</li>
            <li class="ui-state-default">J</li>
          </ol>
        </div>
      </div>
      <div class="footer">Footer1</div>
    </div>

    You should be able to use CSS Grid to achieve what you want if you are willing to replace table with them:

    $(function() {
      $("#selectable1").selectable();
      $("#selectable2").selectable();
    });
    body {
      margin: 0;
      padding: 0;
    }
    
    .header,
    .footer {
      background: yellow;
    }
    
    div.table {
      display: grid;
      width: 100vw;
      height: 100vh;
    }
    
    div.container {
      display: grid;
      grid-template-columns: auto 140px;
      grid-column-gap: 10px;
      overflow: auto;
    }
    
    div.container div {
      overflow-y: auto;
      height: 100%;
    }
    
    #selectable1 {
      list-style-type: none;
      margin: 0;
      padding: 0;
      flex: 1;
    }
    
    #selectable2 {
      list-style-type: none;
      margin: 0;
      padding: 0;
    }
    
    #selectable1 li,
    #selectable2 li {
      margin: 3px;
      padding: 1px;
      float: left;
      width: 100px;
      height: 80px;
      font-size: 4em;
      text-align: center;
    }
    <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
    <div class="table">
      <div class="header">Header1</div>
      <div class="container">
        <div>
          <ol id="selectable1">
            <li class="ui-state-default">1</li>
            <li class="ui-state-default">2</li>
            <li class="ui-state-default">3</li>
            <li class="ui-state-default">4</li>
            <li class="ui-state-default">5</li>
            <li class="ui-state-default">6</li>
            <li class="ui-state-default">7</li>
            <li class="ui-state-default">8</li>
            <li class="ui-state-default">9</li>
            <li class="ui-state-default">10</li>
            <li class="ui-state-default">11</li>
            <li class="ui-state-default">12</li>
          </ol>
        </div>
        <div>
          <ol id="selectable2">
            <li class="ui-state-default">A</li>
            <li class="ui-state-default">B</li>
            <li class="ui-state-default">C</li>
            <li class="ui-state-default">D</li>
            <li class="ui-state-default">E</li>
            <li class="ui-state-default">F</li>
            <li class="ui-state-default">G</li>
            <li class="ui-state-default">H</li>
            <li class="ui-state-default">I</li>
            <li class="ui-state-default">J</li>
          </ol>
        </div>
      </div>
      <div class="footer">Footer1</div>
    </div>