12

I'm trying to add double arrows (up and down) to my table like the tablesorter plugin does.

Here is my fiddle. For some reason, not even one arrow shows up in jsfiddle, but it works on my original table.

I tried this:

$("table th").addClass("headerSortUp");
$("table th").addClass("headerSortDown");

But it didn't work. Any idea how I could do it?

hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Cornwell
  • 3,304
  • 7
  • 51
  • 84

9 Answers9

28

The best solution without images, pure CSS. Just put the classnames headerSortDown and headerSortUp on the td or th rows and the caret will appear.

table td,
table th {
  border: 1px solid silver;
}

.headerSortDown:after,
.headerSortUp:after {
  content: ' ';
  position: relative;
  left: 2px;
  border: 8px solid transparent;
}

.headerSortDown:after {
  top: 10px;
  border-top-color: silver;
}

.headerSortUp:after {
  bottom: 15px;
  border-bottom-color: silver;
}

.headerSortDown,
.headerSortUp {
  padding-right: 10px;
}
<table>
  <thead>
    <tr>
      <th class="headerSortDown">ID</th>
      <th class="headerSortUp">Username</th>
      <th>Fullname</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>John</td>
      <td>John Doe</td>
    </tr>
    <tr>
      <td>2</td>
      <td>Jenny</td>
      <td>Jenny Smith</td>
    </tr>
    <tr>
      <td>3</td>
      <td>Tom</td>
      <td>Tom Doe</td>
    </tr>
  </tbody>
</table>

Also check my JSFiddle: http://jsfiddle.net/rTXXz/ for a working example.

UPDATE: Fixed for chrome

Vadim Ovchinnikov
  • 13,327
  • 5
  • 62
  • 90
3

I get invalid property value in chrome.

With quotes it works:

background: url("data:image/gif;base64, R0lGODlhFQAJAIAAACMtMP///yH5BAEAAAEALAAAAAAVAAkAAAIXjI+AywnaYnhUMoqt3gZXPmVg94yJVQAAOw=") no-repeat 99%;

I converted the double arrow to base64, too.

JSFiddle

bitWorking
  • 12,485
  • 1
  • 32
  • 38
3

A different approach using unicode chars

Starting off with a default caret for an unsorted table

<th>Table Column ▶</th>

On sort, and depending on the sort order and using Jquery I do this

$(this).text($(this).text().slice(0,-2) + " ▲")

Or

$(this).text($(this).text().slice(0,-2) + " ▼")

There is a one thing though - once a caret is set, sorting another column doesn't reset the caret on the previous column. Not sure this is a problem, but if it does become one, I'd need a function to reset carets of the other column headers.

Here is my JSFiddle

Joviano Dias
  • 1,043
  • 10
  • 13
2

Issue is with your .headerSortUp background. I have changed it with below:

background: url(http://tablesorter.com/themes/blue/bg.gif) no-repeat 99%;

jsFiddle with absolute bg

Manoj Yadav
  • 6,560
  • 1
  • 23
  • 21
2

Here is a descending arrow inline. Unfortunately, I do not know how to make the data smaller, but the resulting image is the same size.

background: url('data:image/gif;base64,R0lGODlhFQAEAPcAAAAAACMtMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAP8ALAAAAAAVAAQAAAgaAP8JHCgwgMGDAQgqXIgw4cKHAw9CnFhwYkAAOw==') no-repeat 99%;

Tyler Forsythe
  • 1,471
  • 17
  • 22
2

if you are using bootstrap using this:

th, td {
    border: 1px solid black;
    text-align: center !important;
    font-size: 0.8rem !important;
  }

  td:hover, th:hover {
    -webkit-box-shadow: 0 0 5px -1px rgba(115, 127, 255, 1);
    -moz-box-shadow: 0 0 5px -1px rgba(115, 127, 255, 1);
    box-shadow: 0 0 5px -1px rgba(115, 127, 255, 1);
    border: 1px solid rgba(115, 127, 255, 1) !important;
  }

  th i{
     cursor: pointer !important;
  }

  th i:hover{
     color: red !important;
  }
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>

<link rel="stylesheet" href="https://pro.fontawesome.com/releases/v5.10.0/css/all.css" integrity="sha384-AYmEC3Yw5cVb3ZcuHtOA93w35dYTsvhLPVnYs9eStHfGJvOvKxVfELGroGkvsg+p" crossorigin="anonymous"/>

<table>
    <thead>
    <tr>
      <th>
        <div class="d-flex flex-row align-items-center">
          <span>ID</span>
          <div class="d-flex flex-column ml-2">
            <i class="fa fa-caret-up"></i>
            <i class="fa fa-caret-down"></i>
          </div>
        </div>
      </th>
      <th>
        <div class="d-flex flex-row align-items-center">
          <span>UserName</span>
          <div class="d-flex flex-column ml-2">
            <i class="fa fa-caret-up"></i>
            <i class="fa fa-caret-down"></i>
          </div>
        </div>
      </th>
    </tr>
    </thead>
  </table>
PouriaDiesel
  • 660
  • 8
  • 11
2

The following example applies styling based on the data-sort-dir attribute added to the th element.

The data-sort-dir attribute can have a value of asc or desc and is added and removed via javascript when the user clicks a header.

$('table.table-sortable th').on('click', function(e) {
  sortTableByColumn(this)
})

function sortTableByColumn(tableHeader) {
  // extract all the relevant details
  let table = tableHeader.closest('table')
  let index = tableHeader.cellIndex
  let sortType = tableHeader.dataset.sortType
  let sortDirection = tableHeader.dataset.sortDir || 'asc' // default sort to ascending

  // sort the table rows
  let items = Array.prototype.slice.call(table.rows);
  let sortFunction = getSortFunction(sortType, index, sortDirection)
  let sorted = items.sort(sortFunction)

  // remove and re-add rows to table
  for (let row of sorted) {
    let parent = row.parentNode
    let detatchedItem = parent.removeChild(row)
    parent.appendChild(row)
  }

  // reset heading values and styles
  for (let header of tableHeader.parentNode.children) {
    header.classList.remove('currently-sorted')
    delete header.dataset.sortDir
  }

  // update this headers's values and styles
  tableHeader.dataset.sortDir = sortDirection == 'asc' ? 'desc' : 'asc'
  tableHeader.classList.add('currently-sorted')
}

function getSortFunction(sortType, index, sortDirection) {
  let dir = sortDirection == 'asc' ? -1 : 1
  switch (sortType) {
    case 'text': return stringRowComparer(index, dir);
    case 'numeric': return numericRowComparer(index, dir);
    default: return stringRowComparer(index, dir);
  }
}

// asc = alphanumeric order - eg 0->9->a->z
// desc = reverse alphanumeric order - eg z->a->9->0
function stringRowComparer(index, direction) {
  return (a, b) => -1 * direction * a.children[index].textContent.localeCompare(b.children[index].textContent)
}

// asc = higest to lowest - eg 999->0
// desc = lowest to highest - eg 0->999
function numericRowComparer(index, direction) {
  return (a, b) => direction * (Number(a.children[index].textContent) - Number(b.children[index].textContent))
}
table.table-sortable th.currently-sorted[data-sort-dir="asc"]::after {
    content: "\25b2";
}

table.table-sortable th.currently-sorted[data-sort-dir="desc"]::after {
    content: "\25bc";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table class="table-sortable">
    <thead>
        <tr>
            <th data-sort-type="text">Course</th>
            <th data-sort-type="numeric">In Progress</th>
            <th data-sort-type="numeric">Not Started</th>
            <th data-sort-type="numeric">Passed</th>
            <th data-sort-type="numeric">Failed</th>
        </tr>
    </thead>
    <tbody>
      <tr>
        <td>How to be good at stuff</td>
        <td>0</td>
        <td>1000</td>
        <td>0</td>
        <td>0</td>
      </tr>
      <tr>
        <td>Quantum physics for artists</td>
        <td>200</td>
        <td>6</td>
        <td>66</td>
        <td>66</td>
      </tr>
      <tr>
        <td>The best way to skin a cat</td>
        <td>34</td>
        <td>16</td>
        <td>200</td>
        <td>7</td>
      </tr>
      <tr>
        <td>Human cookbook</td>
        <td>4</td>
        <td>7</td>
        <td>4</td>
        <td>50</td>
      </tr>
      <tr>
        <td>Aristocracy rules</td>
        <td>100</td>
        <td>3</td>
        <td>6</td>
        <td>18</td>
      </tr>
    </tbody>
</table>
br3nt
  • 9,017
  • 3
  • 42
  • 63
1

I was able to get it to work using another background image instead of what you were using. Maybe this can give you some insight into the problem:

.headerSortUp {
  background: url(http://placehold.it/25x25) no-repeat 99%;
}
.headerSortDown {
  background: url(http://placehold.it/25x25) no-repeat 99%;
}

Fiddle

pertrai1
  • 4,146
  • 11
  • 46
  • 71
0

Note: I am adding this answer because it offers an alternative way to add the arrows without using an image but does follow the logic of keeping the arrows in the background.

A way to add the arrows without an image while keeping that styling of the images (just have to tweak it to taste and I didn't optimize the divs or the logic in the css ~ more of a proof of concept (fast prototype)). Another benefit of this approach is that you can easily change the arrows coloring with classes plus if you place the two arrows in separate divs you could even hide one when it is already selected (currently they just change color separately on hover).

See the example in action!

HTML

<table class="test-table">
  <tr class="headRow">
    <th>
<div class="table-head-container">
    <div class="table-head-background">
      <div class="right-text">
        <div class="small-frame">
            <div class="up-arrow">&#9650</div>
            <div class="down-arrow">&#9660</div>
        </div>
      </div>
    </div>
  <div class="Col-header">First</div>
</div>
    </th>
    <th>
<div class="table-head-container">
    <div class="table-head-background">
      <div class="right-text">
        <div class="small-frame">
            <div class="up-arrow">&#9650</div>
            <div class="down-arrow">&#9660</div>
        </div>
      </div>
    </div>
  <div class="Col-header">Last</div>
</div>
     </th>
    <th>
<div class="table-head-container">
    <div class="table-head-background">
      <div class="right-text">
        <div class="small-frame">
            <div class="up-arrow">&#9650</div>
            <div class="down-arrow">&#9660</div>
        </div>
      </div>
    </div>
  <div class="Col-header">Phone</div>
</div>
    </th>
  </tr>
  <tr>
    <td>John</td>
    <td>Doe</td>
    <td>555-5555</td>
  </tr>
  <tr class="evenRow">
    <td>Jane</td>
    <td>Smith</td>
    <td>555-5555</td>
  </tr>
  <tr>
    <td>Homer</td>
    <td>Simpson</td>
    <td>555-5555</td>
  </tr>
</table>

CSS

.table-head-container {
   position: relative;
  color: white;
  max-width: 100px;
}

.test-table {
  border: solid black 1px;
}

.headRow {
  background-color: green;
  color: white;
}

.headRow > th {
  border: solid black 2px;
  padding: 10px 20px 10px 5px;
  min-width:100px;
  font-size: 1.6em
}

.evenRow {
  background-color: #E8E8E8;
}

table {
  border-collapse: collapse;
}

tr > td {
  border: solid black 1px;
  padding: 5px;
}

.Col-header {
  text-align: left;
}

.table-head-background {
   position: absolute;
   top: -10;
   left: 15;
   bottom: 0;
   right: 0;
   z-index: 1;
  width: 0;
  color: white;
  background-color:green;
}

.table-head-background > .right-text {
  text-align: right;
}

.table-head-background > .right-text > .small-frame {
  position: absolute;
  left: 80px;
  width: 5px !important;
  word-wrap: break-word;
}

.table-head-background > .right-text > .small-frame > .up-arrow, .table-head-background > .right-text > .small-frame > .down-arrow {
font-size: .8em;
}

.table-head-background > .right-text > .small-frame > .up-arrow:hover, .table-head-background > .right-text > .small-frame > .down-arrow:hover {
    color: blue !important;
}
Lee Curran
  • 19
  • 6