Сортування таблиці jQuery


177

У мене дуже проста таблиця HTML з 4 колонками:

Facility Name, Phone #, City, Specialty

Я хочу, щоб користувач міг сортувати лише за назвою об'єкта та містом .

Як я можу кодувати це за допомогою jQuery?


Мій голос - TinyTable
перегляньте

Відповіді:


152

Якщо ви хочете уникнути всіх дзвіночків, то я можу запропонувати цей простий sortElementsплагін . Використання:

var table = $('table');

$('.sortable th')
    .wrapInner('<span title="sort this column"/>')
    .each(function(){

        var th = $(this),
            thIndex = th.index(),
            inverse = false;

        th.click(function(){

            table.find('td').filter(function(){

                return $(this).index() === thIndex;

            }).sortElements(function(a, b){

                if( $.text([a]) == $.text([b]) )
                    return 0;

                return $.text([a]) > $.text([b]) ?
                    inverse ? -1 : 1
                    : inverse ? 1 : -1;

            }, function(){

                // parentNode is the element we want to move
                return this.parentNode; 

            });

            inverse = !inverse;

        });

    });

І демонстрація. (для сортування натисніть заголовки стовпців "місто" та "об'єкт")


6
Демонстрація була зламана, оскільки розташування плагіна змінилося. Я відправив фіксовану jsfiddle до демо sortElements, який, принаймні, здається, працює для мене :) @ 999, можливо, ви можете оновити свою відповідь, щоб посилатися на фіксовану демонстрацію?
Джейк Уоррелл

2
Що робити, якщо у вас є кілька таблиць на сторінці? Я роздвоїв jsfiddle jsfiddle.net/CM8bT
Marc

1
Я отримую цю помилку Error: illegal characterhtml точно не збігається, у мене також є thead та tboy, чи можете ви мені допомогти з цим?
pahnin

1
Зазначена вище функція не буде працювати у випадку чутливості до справ. У цьому плагіні 'a'! = 'A'. Це спрацює, якщо перетворити текст у великі чи малі регістри, а потім перевірити та порівняти. Наприклад: Замість $.text([a]) == $.text([b])використання $.text([a]).toUpperCase() == $.text([b]).toUpperCase()виправите це.
NBK

1
Досить скоро ви побачите, що сортування зовсім не є специфічною для таблиці проблемою - коли ви це зробите, ось мій крихітний плагін jQuery, який буде сортувати списки, таблиці, значки чи що-небудь ще, у порядку зростання чи зменшення. Я також використовував його для сортування за різними типами даних, наприклад валютою чи роком - просто надайте власну функцію, яка повертає дані за сортуванням. (Мені подобається тримати ці функції окремо і давати їм значущі імена, будувати власну маленьку бібліотеку "способів сортування речей", специфічних для рішення, яке
будую

184

Я натрапив на це, і думав, що кину свої 2 копійки. Клацніть на заголовки стовпців для сортування за зростанням та ще раз для сортування за спаданням.

  • Працює в Chrome, Firefox, Opera І IE (8)
  • Використовує лише JQuery
  • Чи алфавітно-числове сортування - висхідне та низхідне

$('th').click(function(){
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc){rows = rows.reverse()}
    for (var i = 0; i < rows.length; i++){table.append(rows[i])}
})
function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index)
        return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).text() }
table, th, td {
    border: 1px solid black;
}
th {
    cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
    <tr><th>Country</th><th>Date</th><th>Size</th></tr>
    <tr><td>France</td><td>2001-01-01</td><td>25</td></tr>
    <tr><td><a href=#>spain</a></td><td>2005-05-05</td><td></td></tr>
    <tr><td>Lebanon</td><td>2002-02-02</td><td>-17</td></tr>
    <tr><td>Argentina</td><td>2005-04-04</td><td>100</td></tr>
    <tr><td>USA</td><td></td><td>-6</td></tr>
</table>

** Оновлення: 2018 рік


10
Фантастичний! Просто зауважте, що якщо у вас є посилання на tds, наприклад, <a href="#">Test</a>сортування стосується <a.... Для сортування за текстом потрібно лише змінити html()в останньому рядку на text().
Кай Ноак

1
@wubblyjuggly - що ти спробував? В даний час таблиця використовує дані комірок (наприклад, значення html) для визначення типу даних (тобто числа або рядка). Оскільки рядки дат надходять у багатьох форматах, писати загальний детектор / аналізатор дати (недоцільно) можна недописати (ви могли б переписати, comparer(..)якби точно знали, який формат хочете підтримувати). Тим часом, якщо ви використовуєте yyyy-MM-dd, " string" сортування буде замовляти дані для вас. наприклад, jsbin.com/pugedip/1
Нік Грілі

1
Цей приклад відмінно працював для мене, коли обраного рішення не було. Обрана відповідь не працювала для мене; Я не впевнений, чи це тому, що я використовую thead / tbody чи ні (jsfiddle, без цих тегів, працювала).
RalphTheWonderLlama

1
Дякую @Jan, я включив вашу пропозицію в рішення!
Нік Грілі

1
@NickGrealy Ви праві, мої пропозиції в коментарі, де саме відхилена редакція. Порівняйте jsfiddle.net/gn1vtcLq/2 (моя версія) з jsfiddle.net/0a15ky9u (ваша версія). Клацніть на заголовку "Секс" кілька разів, щоб побачити, за допомогою яких ідентифікаторів або імен згодом змінюється порядок у вашій версії, зберігаючи їх впорядкований порядок у моїй версії.
markus s

39

На сьогоднішній день, найпростіший з них, який я використовував: http://datatables.net/

Дивовижно просте ... просто переконайтесь, що ви переходите до маршруту заміни DOM (IE, будуючи таблицю і дозволяючи DataTables переформатувати її), то переконайтеся, що відформатуйте вашу таблицю <thead>і <tbody>чи вона не працюватиме. Це про єдиний готч.

Також є підтримка AJAX і т. Д. Як і у всіх справді хороших фрагментів коду, це також ДУЖЕ легко відключити. Ти б здивувався тим, що ти можеш використати. Я почав з "голого" DataTable, який сортував лише одне поле, а потім зрозумів, що деякі функції дійсно стосуються того, що я роблю. Клієнти ЛЮБИТЬ нові функції.

Бонус вказує на DataTables за повну підтримку ThemeRoller ....

У мене теж було пощастило з tableorter, але це не так просто, не так добре зафіксовано і має лише нормальні функції.


4
Погоджено, що це гарний плагін з великими можливостями, однак, можливо, надмірність у плані складності та розміру для того, що вимагає ОП.
переосмислити

2
+1 за те, що вони доступні в NuGet: nuget.org/List/Packages/jquery.datatables
Франк ван Ейкелен

1
Я теж погоджуюся, datatables.net - найкращий сортувальник таблиць / інструментів для пошуку сторінок / пошукових запитів. Його багаті риси заощадили мені багато часу. Я тільки шкодую про витрачений час, намагаючись інтегрувати плагін tableorter2 до своїх кодів, перш ніж дізнатися про таблиці даних ...
Логан

2
Я знаю, що це стара тема, але ця відповідь все ще діє. Напевно, найпростіший плагін, який я коли-небудь використовував. Знадобилося 5 хв, щоб підняти його і сортувати мій стіл. Дякую!
Trucktech

Дуже просто налаштувати, найкраще я користувався.
Рог

18

Ми щойно почали використовувати цей інструмент гладкого: https://plugins.jquery.com/tablesorter/

Є відео про його використання за адресою: http://www.highoncoding.com/Articles/695_Sorting_GridView_Using_JQuery_TableSorter_Plug_in.aspx

    $('#tableRoster').tablesorter({
        headers: {
            0: { sorter: false },
            4: { sorter: false }
        }
    });

За допомогою простої таблиці

<table id="tableRoster">
        <thead> 
                  <tr>
                    <th><input type="checkbox" class="rCheckBox" value="all" id="rAll" ></th>
                    <th>User</th>
                    <th>Verified</th>
                    <th>Recently Accessed</th>
                    <th>&nbsp;</th>
                  </tr>
        </thead>

15

Моя відповідь була б "обережно". Багато додатків для сортування таблиць jQuery сортують лише те, що ви передаєте в браузер. У багатьох випадках потрібно пам’ятати, що таблиці - це динамічні набори даних, які потенційно можуть містити мільйони рядків даних.

Ви згадуєте, що у вас є лише 4 стовпці, але набагато важливіше, ви не згадуєте, скільки рядків ми говоримо тут.

Якщо ви передаєте 5000 рядків у браузер із бази даних, знаючи, що фактична таблиця бази даних містить 100 000 рядків, моє питання: який сенс робити таблицю сортовою? Для того, щоб зробити належне сортування, вам доведеться відправити запит назад до бази даних, і дозволити базі даних (інструменту, який фактично призначений для сортування даних), сортувати за вас.

Що стосується прямої відповіді на ваше запитання, найкращим доповненням для сортування, на які я потрапила, є Інгрід. Є багато причин, що мені не подобається цей додаток ("непотрібні дзвіночки ...", як ви це називаєте), але одна з найкращих його функцій з точки зору сортування - це те, що він використовує ajax, а не " t припустимо, що ви вже передали йому всі дані, перш ніж вона зробить їхнє сортування.

Я усвідомлюю, що ця відповідь, ймовірно, є надмірною (і запізнилася понад 2 роки) на ваші вимоги, але я дратуюся, коли розробники в моїй галузі не помічають цього питання. Тож сподіваюся, що хтось інший підбере це.

Зараз я почуваюся краще.


7

Це хороший спосіб сортування таблиці:

$(document).ready(function () {
                $('th').each(function (col) {
                    $(this).hover(
                            function () {
                                $(this).addClass('focus');
                            },
                            function () {
                                $(this).removeClass('focus');
                            }
                    );
                    $(this).click(function () {
                        if ($(this).is('.asc')) {
                            $(this).removeClass('asc');
                            $(this).addClass('desc selected');
                            sortOrder = -1;
                        } else {
                            $(this).addClass('asc selected');
                            $(this).removeClass('desc');
                            sortOrder = 1;
                        }
                        $(this).siblings().removeClass('asc selected');
                        $(this).siblings().removeClass('desc selected');
                        var arrData = $('table').find('tbody >tr:has(td)').get();
                        arrData.sort(function (a, b) {
                            var val1 = $(a).children('td').eq(col).text().toUpperCase();
                            var val2 = $(b).children('td').eq(col).text().toUpperCase();
                            if ($.isNumeric(val1) && $.isNumeric(val2))
                                return sortOrder == 1 ? val1 - val2 : val2 - val1;
                            else
                                return (val1 < val2) ? -sortOrder : (val1 > val2) ? sortOrder : 0;
                        });
                        $.each(arrData, function (index, row) {
                            $('tbody').append(row);
                        });
                    });
                });
            });
            table, th, td {
            border: 1px solid black;
        }
        th {
            cursor: pointer;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
        <tr><th>id</th><th>name</th><th>age</th></tr>
        <tr><td>1</td><td>Julian</td><td>31</td></tr>
        <tr><td>2</td><td>Bert</td><td>12</td></tr>
        <tr><td>3</td><td>Xavier</td><td>25</td></tr>
        <tr><td>4</td><td>Mindy</td><td>32</td></tr>
        <tr><td>5</td><td>David</td><td>40</td></tr>
    </table>

Загадку можна знайти тут:
https://jsfiddle.net/e3s84Luw/

Пояснення можна знайти тут: https://www.learningjquery.com/2017/03/how-to-sort-html-table-using-jquery-code


Цей дуже простий десорсер дуже добре працює з динамічними даними таблиці (php + MariaDB). Дякую!
yello

6

Мені подобається ця прийнята відповідь, проте рідко ви отримуєте вимоги до сортування html та не потрібно додавати піктограми, що вказують напрямок сортування. Я взяв приклад використання прийому відповіді та швидко це виправив, просто додавши завантажувальний проект до свого проекту та додавши наступний код:

<div></div>

всередині кожного, <th>щоб у вас було місце встановити значок.

setIcon(this, inverse);

з використання прийнятої відповіді під рядком:

th.click(function () {

і додавши метод setIcon:

function setIcon(element, inverse) {

        var iconSpan = $(element).find('div');

        if (inverse == false) {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('icon-white icon-arrow-up');
        } else {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('icon-white icon-arrow-down');
        }
        $(element).siblings().find('div').removeClass();
    }

Ось демонстрація . - Вам потрібно або запустити демонстрацію у Firefox або IE, або відключити перевірку типу MIME Chrome для того, щоб демонстрація працювала. Це залежить від плагіну sortElements, пов'язаного прийнятою відповіддю, як зовнішнього ресурсу. Просто голови вгору!



2

@Nick Grealy відповідь чудова, але вона не враховує можливих rowspanатрибутів комірок заголовка таблиці (і, ймовірно, інші відповіді теж не роблять цього). Ось вдосконалення відповіді @Nick Grealy, яке виправляє це. Виходячи з цієї відповіді теж (дякую @Andrew Orlov).

Я також замінив $.isNumericфункцію на власну (спасибі @zad), щоб змусити її працювати зі старими версіями jQuery.

Щоб активувати його, додайте class="sortable"до <table>тегу.

$(document).ready(function() {

    $('table.sortable th').click(function(){
        var table = $(this).parents('table').eq(0);
        var column_index = get_column_index(this);
        var rows = table.find('tbody tr').toArray().sort(comparer(column_index));
        this.asc = !this.asc;
        if (!this.asc){rows = rows.reverse()};
        for (var i = 0; i < rows.length; i++){table.append(rows[i])};
    })

});

function comparer(index) {
    return function(a, b) {
        var valA = getCellValue(a, index), valB = getCellValue(b, index);
        return isNumber(valA) && isNumber(valB) ? valA - valB : valA.localeCompare(valB);
    }
}
function getCellValue(row, index){ return $(row).children('td').eq(index).html() };

function isNumber(n) {
  return !isNaN(parseFloat(n)) && isFinite(n);
}

function get_column_index(element) {
    var clickedEl = $(element);
    var myCol = clickedEl.closest("th").index();
    var myRow = clickedEl.closest("tr").index();
    var rowspans = $("th[rowspan]");
    rowspans.each(function () {
        var rs = $(this);
        var rsIndex = rs.closest("tr").index();
        var rsQuantity = parseInt(rs.attr("rowspan"));
        if (myRow > rsIndex && myRow <= rsIndex + rsQuantity - 1) {
            myCol++;
        }
    });
    // alert('Row: ' + myRow + ', Column: ' + myCol);
    return myCol;
};

Що робити, якщо ви де сортуєте за датою?
віблуогглю

@wubblyjuggly ви можете замінити функцію компаратора з тим , що зіставляє дати, дивіться , наприклад , stackoverflow.com/questions/10636779/jquery-date-sorting
Денніс Голомазов

1
Браво, я спробував десятки сортувальників, твій єдиний, хто працює на мене. До речі, мої дати в текстовому форматі (2020.02.23), тому для мене це не проблема
Манні Рамірес

2

Ви можете використовувати плагін jQuery ( Brejdjs ), який забезпечує сортування, фільтрування та пагинацію:

HTML:

<table>
  <thead>
    <tr>
      <th sort='name'>Name</th>
      <th>Phone</th>
      <th sort='city'>City</th>
      <th>Speciality</th>
    </tr>
  </thead>
  <tbody>
    <tr b-scope="people" b-loop="person in people">
      <td b-sort="name">{{person.name}}</td>
      <td>{{person.phone}}</td>
      <td b-sort="city">{{person.city}}</td>
      <td>{{person.speciality}}</td>
    </tr>
  </tbody>
</table>

JS:

$(function(){
  var data = {
    people: [
      {name: 'c', phone: 123, city: 'b', speciality: 'a'},
      {name: 'b', phone: 345, city: 'a', speciality: 'c'},
      {name: 'a', phone: 234, city: 'c', speciality: 'b'},
    ]
  };
  breed.run({
    scope: 'people',
    input: data
  });
  $("th[sort]").click(function(){
    breed.sort({
      scope: 'people',
      selector: $(this).attr('sort')
    });
  });
});

Робочий приклад на скрипці


2

Цей веб-переглядач не відключає веб-переглядача, легко налаштовується далі:

var table = $('table');

$('th.sortable').click(function(){
    var table = $(this).parents('table').eq(0);
    var ths = table.find('tr:gt(0)').toArray().sort(compare($(this).index()));
    this.asc = !this.asc;
    if (!this.asc)
       ths = ths.reverse();
    for (var i = 0; i < ths.length; i++)
       table.append(ths[i]);
});

function compare(idx) {
    return function(a, b) {
       var A = tableCell(a, idx), B = tableCell(b, idx)
       return $.isNumeric(A) && $.isNumeric(B) ? 
          A - B : A.toString().localeCompare(B)
    }
}

function tableCell(tr, index){ 
    return $(tr).children('td').eq(index).text() 
}

1
Це здається найкращим рішенням. Для цього не потрібен плагін. Перший рядок ви можете видалити, потім у готовий документ вставте блок $ ('th.sortable'). Click (...). Дайте заголовкам таблиці сортувати клас, і ви закінчили. <th class = 'sortable> title </th>. Працює чарівно для стовпців з текстом або цифрами.
pizzamonster

1

На відповідь Джеймса я лише зміню функцію сортування, щоб зробити її більш універсальною. Таким чином він буде сортувати текст за алфавітом та числами, як числа.

if( $.text([a]) == $.text([b]) )
    return 0;
if(isNaN($.text([a])) && isNaN($.text([b]))){
    return $.text([a]) > $.text([b]) ? 
       inverse ? -1 : 1
       : inverse ? 1 : -1;
}
else{
    return parseInt($.text([a])) > parseInt($.text([b])) ? 
      inverse ? -1 : 1
      : inverse ? 1 : -1;
}

1

Ще один підхід до сортування таблиці HTML. (на основі сортування HTML W3.JS )

/* Facility Name */
$('#bioTable th:eq(0)').addClass("control-label pointer");
/* Phone # */
$('#bioTable th:eq(1)').addClass("not-allowed");
/* City */
$('#bioTable th:eq(2)').addClass("control-label pointer");
/* Specialty */
$('#bioTable th:eq(3)').addClass("not-allowed");


var collection = [{
  "FacilityName": "MinION",
  "Phone": "999-8888",
  "City": "France",
  "Specialty": "Genetic Prediction"
}, {
  "FacilityName": "GridION X5",
  "Phone": "999-8812",
  "City": "Singapore",
  "Specialty": "DNA Assembly"
}, {
  "FacilityName": "PromethION",
  "Phone": "929-8888",
  "City": "San Francisco",
  "Specialty": "DNA Testing"
}, {
  "FacilityName": "iSeq 100 System",
  "Phone": "999-8008",
  "City": "Christchurch",
  "Specialty": "gDNA-mRNA sequencing"
}]

$tbody = $("#bioTable").append('<tbody></tbody>');

for (var i = 0; i < collection.length; i++) {
  $tbody = $tbody.append('<tr class="item"><td>' + collection[i]["FacilityName"] + '</td><td>' + collection[i]["Phone"] + '</td><td>' + collection[i]["City"] + '</td><td>' + collection[i]["Specialty"] + '</td></tr>');
}
.control-label:after {
  content: "*";
  color: red;
}

.pointer {
  cursor: pointer;
}

.not-allowed {
  cursor: not-allowed;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.w3schools.com/lib/w3.js"></script>
<link href="https://www.w3schools.com/w3css/4/w3.css" rel="stylesheet" />
<p>Click the <strong>table headers</strong> to sort the table accordingly:</p>

<table id="bioTable" class="w3-table-all">
  <thead>
    <tr>
      <th onclick="w3.sortHTML('#bioTable', '.item', 'td:nth-child(1)')">Facility Name</th>
      <th>Phone #</th>
      <th onclick="w3.sortHTML('#bioTable', '.item', 'td:nth-child(3)')">City</th>
      <th>Specialty</th>
    </tr>
  </thead>
</table>


1

Нарешті я використав відповідь Ніка (найпопулярніший, але не прийнятий) https://stackoverflow.com/a/19947532/5271220

і поєднав його з https://stackoverflow.com/a/16819442/5271220, але не хотів додавати піктограми чи приємно в проект. Стилі CSS для сортування стовпців-asc / desc я зробив кольором, набиванням, округлою облямівкою.

Я також модифікував його для класу, а не для будь-якого, щоб ми могли контролювати, які з них можна сортувати. Це також може стати в нагоді пізніше, якщо є дві таблиці, хоча для цього потрібно буде зробити більше модифікацій.

корпус:

 html += "<thead>\n";
    html += "<th></th>\n";
    html += "<th class=\"sort-header\">Name <span></span></i></th>\n";
    html += "<th class=\"sort-header\">Status <span></span></th>\n";
    html += "<th class=\"sort-header\">Comments <span></span></th>\n";
    html += "<th class=\"sort-header\">Location <span></span></th>\n";
    html += "<th nowrap class=\"sort-header\">Est. return <span></span></th>\n";
    html += "</thead>\n";
    html += "<tbody>\n"; ...

... далі вниз по тілу

$("body").on("click", ".sort-header", function (e) {
    var table = $(this).parents('table').eq(0)
    var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
    this.asc = !this.asc
    if (!this.asc) { rows = rows.reverse() }
    for (var i = 0; i < rows.length; i++) { table.append(rows[i]) }

    setIcon(e.target, this.asc);
});

функції:

function comparer(index) {
        return function (a, b) {
            var valA = getCellValue(a, index), valB = getCellValue(b, index)
            return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.toString().localeCompare(valB)
        }
    }

    function getCellValue(row, index) {
        return $(row).children('td').eq(index).text()
    }

    function setIcon(element, inverse) {

        var iconSpan = $(element).find('span');

        if (inverse == true) {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('sort-column-asc');
            $(iconSpan)[0].innerHTML = " &#8593 " // arrow up
        } else {
            $(iconSpan).removeClass();
            $(iconSpan).addClass('sort-column-desc');
            $(iconSpan)[0].innerHTML = " &#8595 " // arrow down 
        }

        $(element).siblings().find('span').each(function (i, obj) {
            $(obj).removeClass();
            obj.innerHTML = "";
        });
    }

-4

Мій голос! jquery.sortElements.js та простий jquery
Дуже простий, дуже простий, завдяки nandhp ...

            $('th').live('click', function(){

            var th = $(this), thIndex = th.index(), var table = $(this).parent().parent();

                switch($(this).attr('inverse')){
                case 'false': inverse = true; break;
                case 'true:': inverse = false; break;
                default: inverse = false; break;
                }
            th.attr('inverse',inverse)

            table.find('td').filter(function(){
                return $(this).index() === thIndex;
            }).sortElements(function(a, b){
                return $.text([a]) > $.text([b]) ?
                    inverse ? -1 : 1
                    : inverse ? 1 : -1;
            }, function(){
                // parentNode is the element we want to move
                return this.parentNode; 
            });
            inverse = !inverse;     
            });

Dei uma melhorada do código
Одна треска краще! Функція для всіх таблиць у всіх Th за весь час ... Подивіться!
DEMO


3
Окрім того, що не в змозі зрозуміти слово, я настійно рекомендую проти .live().
втілився
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.