Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add sorting arrows to <th> like table sorter

Tags:

jquery

css

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?

like image 461
Cornwell Avatar asked Jul 14 '13 12:07

Cornwell


6 Answers

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

like image 38
Joviano Dias Avatar answered Sep 20 '22 19:09

Joviano Dias


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

like image 112
Kapitein Witbaard Avatar answered Nov 20 '22 09:11

Kapitein Witbaard


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>
like image 39
br3nt Avatar answered Nov 20 '22 08:11

br3nt


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

like image 3
bitWorking Avatar answered Nov 20 '22 10:11

bitWorking


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

like image 2
Manoj Yadav Avatar answered Nov 20 '22 09:11

Manoj Yadav


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%;

like image 2
Tyler Forsythe Avatar answered Nov 20 '22 10:11

Tyler Forsythe