Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Функция для сортировки таблицы (https://javascript.ru/forum/misc/75800-funkciya-dlya-sortirovki-tablicy.html)

JStudent 07.11.2018 17:07

Функция для сортировки таблицы
 
Привет.
Есть функция которая сортирует колонку по возростанию по клику на хэдер.
При повторном клике сортируется по убыванию.
То что я написал мне не сильно нравится.

Как правильно организовать логику сортировки?

https://codepen.io/everest08/pen/KrdPLP

Malleys 07.11.2018 18:30

codepen.io/Malleys/pen/dQGMbP

JStudent 07.11.2018 18:59

Агонь.:victory:

:blink: Не сразу понял откуда берётся 1 в data-order
Спасибо

рони 07.11.2018 19:17

сортировка таблицы по клику на ячейку первой строки es6.
 
:write:
<!DOCTYPE html>

<html>
<head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <style class="cp-pen-styles">@import url('https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700');
body {
    font-family: 'Roboto';
}
td, th {
    border: 2px solid red;
    width: 150px;
    height: 40px;
    text-align: center;
}

table {
    border-collapse: collapse;
    margin: 20px auto;
}
th {
    cursor: pointer;
}</style>
</head>

<body>
<table class="sort" id="sort" align="center">
    <tr id="zag">
        <td>ID</td>
        <td>Имя</td>
        <td>Фамилия</td>
        <td>Сайт</td>
        <td>Переключалка стилей</td>
    </tr>
    <tr>
        <td>1</td>
        <td>Александр</td>
        <td>Шуркаев</td>
        <td><a href="#">htmlcoder.visions.ru</a></td>
        <td>Не-а</td>
    </tr>
    <tr>
        <td>123</td>
        <td>Пол</td>
        <td>Соуден</td>
        <td><a href="#">idontsmoke.co.uk</a></td>
        <td>Угу</td>
    </tr>
    <tr>
        <td>3</td>
        <td>Джеффри</td>
        <td>Зельдман</td>
        <td><a href="#">zeldman.com</a></td>
        <td>Угу</td>
    </tr>
    <tr>
        <td>44</td>
        <td>Аарон</td>
        <td>Будман</td>
        <td><a href="#">youngpup.net</a></td>
        <td>Не-а</td>
    </tr>
    <tr>
        <td>11</td>
        <td>Глен</td>
        <td>Мерфи</td>
        <td><a href="#">glenmurphy.com</a></td>
        <td>Не-а</td>
    </tr>
    <tr>
        <td>15</td>
        <td>Даниель</td>
        <td>Боган</td>
        <td><a href="#">waferbaby.com</a></td>
        <td>Не-а</td>
    </tr>
    <tr>
        <td>33</td>
        <td>Ден</td>
        <td>Бенджамин</td>
        <td><a href="#">hivelogic.com</a></td>
        <td>Угу</td>
    </tr>

</table>
<table class="sort" align="center">
                <thead>
                        <tr>
                                <th>Name</th>
                                <th>SecondName</th>
                                <th>Patronymic</th>
                                <th>Age</th>
                        </tr>
                </thead>
                <tbody>
                        <tr>
                                <td>Макс</td>
                                <td>Троцкий</td>
                                <td>Ильич</td>
                                <td>77</td>
                        </tr>
                        <tr>
                                <td>Вася</td>
                                <td>Петров</td>
                                <td>Александрович</td>
                                <td>21</td>
                        </tr>
                        <tr>
                                <td>Петя</td>
                                <td>Иванов</td>
                                <td>Петрович</td>
                                <td>15</td>
                        </tr>
                        <tr>
                                <td>Миша</td>
                                <td>Ложкин</td>
                                <td>Васильевич</td>
                                <td>43</td>
                        </tr>
                        <tr>
                                <td>Владимир</td>
                                <td>Сидоров</td>
                                <td>Игоревич</td>
                                <td>33</td>
                        </tr>
                        <tr>
                                <td>Коля</td>
                                <td>Колбаскин</td>
                                <td>Олегович</td>
                                <td>41</td>
                        </tr>
</tbody>
        </table>
<script>
addEventListener("load", function() {
    (function(f) {
        function g(c) {
            return function(b, a) {
                b = b.cells[c].textContent;
                a = a.cells[c].textContent;
                b = +b || b;
                a = +a || a;
                return b > a ? 1 : b < a ? -1 : 0
            }
        }

        function init(d) {
            const [{cells}, ...e] = [...d.rows];
            const tbody = e[0].parentNode;
            [...cells].forEach((c, b) => {
                let a = 0;
                c.addEventListener("click", () => {
                    e.sort(g(b));
                    a && e.reverse();
                    tbody.append(...e); 
                    a ^= 1
                })
            })
        }
        document.querySelectorAll(f).forEach(init)

    })(".sort")
});
</script>

</body>
</html>

MC-XOBAHCK 07.11.2018 20:34

рони,
а можете во второй таблице последнюю колонку поменять на Balance и изменить в ней значения чтобы был нуль, значения с десятичными, отрицательные значения и с разным количеством символов (1, 10, 100, 1000).

Я тему добавил в избранное, просто хотелось чтобы сразу код продебажили, ведь сортировка чисел будет посложнее чем букв.

MC-XOBAHCK 07.11.2018 20:49

Цитата:

Сообщение от Malleys (Сообщение 498083)

похоже там баг для чисел.
Сортирует от меньшего большего в таком порядке
1, 1500, 33, 41, 43, 77

рони 07.11.2018 21:04

Цитата:

Сообщение от MC-XOBAHCK
изменить в ней значения

так?
<!DOCTYPE html>

<html>
<head>
    <title>Untitled</title>
    <meta charset="utf-8">
    <style class="cp-pen-styles">@import url('https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700');
body {
    font-family: 'Roboto';
}
td, th {
    border: 2px solid red;
    width: 150px;
    height: 40px;
    text-align: center;
}

table {
    border-collapse: collapse;
    margin: 20px auto;
}
th {
    cursor: pointer;
}</style>
</head>

<body>

<table class="sort" align="center">
                <thead>
                        <tr>
                                <th>Name</th>
                                <th>SecondName</th>
                                <th>Patronymic</th>
                                <th>Age</th>
                        </tr>
                </thead>
                <tbody>
                        <tr>
                                <td>Макс</td>
                                <td>Троцкий</td>
                                <td>Ильич</td>
                                <td>-7700</td>
                        </tr>
                        <tr>
                                <td>Вася</td>
                                <td>Петров</td>
                                <td>Александрович</td>
                                <td>210000</td>
                        </tr>
                        <tr>
                                <td>Петя</td>
                                <td>Иванов</td>
                                <td>Петрович</td>
                                <td>0</td>
                        </tr>
                        <tr>
                                <td>Миша</td>
                                <td>Ложкин</td>
                                <td>Васильевич</td>
                                <td>1043.006</td>
                        </tr>
                        <tr>
                                <td>Владимир</td>
                                <td>Сидоров</td>
                                <td>Игоревич</td>
                                <td>3.05</td>
                        </tr>
                        <tr>
                                <td>Коля</td>
                                <td>Колбаскин</td>
                                <td>Олегович</td>
                                <td>-41.6</td>
                        </tr>
</tbody>
        </table>
<script>
addEventListener("load", function() {
    (function(f) {
        function g(c) {
            return function(b, a) {
                b = b.cells[c].textContent;
                a = a.cells[c].textContent;
                b = +b || b;
                a = +a || a;
                return b > a ? 1 : b < a ? -1 : 0
            }
        }

        function init(d) {
            const [{cells}, ...e] = [...d.rows];
            const tbody = e[0].parentNode;
            [...cells].forEach((c, b) => {
                var a = 0;
                c.addEventListener("click", () => {
                    e.sort(g(b));
                    a && e.reverse();
                    tbody.append(...e);
                    a ^= 1
                })
            })
        }
        document.querySelectorAll(f).forEach(init)

    })(".sort")
});

</script>

</body>
</html>

MC-XOBAHCK 07.11.2018 21:24

Цитата:

Сообщение от рони
так?

Да.
Я не сразу заметил, вот оно где условие
b = +b || b;
a = +a || a;
return b > a ? 1 : b < a ? -1 : 0

Malleys 08.11.2018 01:37

Цитата:

Сообщение от MC-XOBAHCK
похоже там баг для чисел.
Сортирует от меньшего большего в таком порядке
1, 1500, 33, 41, 43, 77

Вообще-то нет! Оно сортировало в алфавитном порядке. Полезно, если, например, нужно отсортировать список телефонных номеров.
Цитата:

Сообщение от MC-XOBAHCK
сортировка чисел будет посложнее чем букв.

Для этого есть Internationalization API. Это не сложнее, чем
new Intl.Collator(["en", "ru"], { numeric: true });
, чтобы сравнивать строки по-русский, по-английский и числа. (ё по-русский будет сравниваться как в алфавите)

На самом деле это очень простая задача и решается она просто! codepen.io/Malleys/pen/dQGMbP

UPD
Цитата:

Сообщение от рони
const [{cells}, ...e] = [...d.rows];

У класса HTMLCollection есть свойство Symbol.iterator, но вы зачем-то используете его от массива. В чём прикол? Я думаю,
const [{cells}, ...e] = d.rows;
достаточно.

Цитата:

Сообщение от рони
e.sort(g(b));
a && e.reverse();

Эту сортировку можно организовать так, чтобы ещё потом не нужно было разворачивать массив.

UPD2
Цитата:

Сообщение от рони
Malleys,
а если так индекс
const index = [...target.parentNode.cells].indexOf(target);

Да, да, да, именно так и надо!

рони 08.11.2018 02:04

Malleys,
а если так индекс
const index = [...target.parentNode.cells].indexOf(target);

рони 08.11.2018 14:06

Цитата:

Сообщение от Malleys
В чём прикол?

в недостатке понимания и знаний.
Цитата:

Сообщение от Malleys
Эту сортировку можно организовать так, чтобы ещё потом не нужно было разворачивать массив.

это понятно.

denis_kontarev 27.09.2019 10:07

А можно ли сделать чтоб поиск шел не по <tbody> , а допустим по какому либо другому тегу <table>?

рони 27.09.2019 10:41

Цитата:

Сообщение от denis_kontarev
А можно ли

???

denis_kontarev 27.09.2019 10:47

Я и спрашиваю есть ли такая возможность?)
У меня стоит фильтр по буквам "А-Я", который работает по <tfoot> и числовой фильтр, который по <tbody>, но вместе эти теги конфликтуют и не получается задействовать сразу два фильтра

рони 27.09.2019 10:55

denis_kontarev,
не понимаю.

denis_kontarev 27.09.2019 11:04

Попробую подробно описать.
Первый фильтр делает поиск по тегу <tfoot> введенные буквы (слова) и при совпадении оставляет нужную информацию.

$(document).ready(function(){
$("#teams_filter").keyup(function(){
_this = this;
$.each($("#table_search tfoot"), function() {
if($(this).text().toLowerCase().indexOf($(_this).val().toLowerCase()) === -1)
$(this).hide();
else
$(this).show();                
});
});
});
<tfoot>.......</tfoot>
<tfoot>.......</tfoot>
<tfoot>.......</tfoot>

А второй фильтр сортирует таблицу по числовому значению от меньшего к большему по тегу <tbody>
document.addEventListener('DOMContentLoaded', () => {
const getSort = ({ target }) => {
    const order = target.dataset.order = -(target.dataset.order || -1);
    const index = [...target.parentNode.cells].indexOf(target);
    const collator = new Intl.Collator(["en", "ru"], { numeric: true });
    const comparator = (index, order) => (a, b) => order * collator.compare(
    a.children[index].innerHTML,
    b.children[index].innerHTML);
    const tBody = target.closest("table").tBodies[0];
    let trs = [...tBody.rows].filter((el, i) => i % 2 == 0);
    trs.sort(comparator(index, order));
    trs.forEach(el => {
    const next = el.nextElementSibling;
    tBody.append(...[el,next])
    });
    for (const cell of target.parentNode.cells)
    cell.classList.toggle("sorted", cell === target);
};
document.querySelector('.tsort thead').addEventListener('click', getSort)
})

Так вот как сделать чтоб фильтр начинал поиск не по <tbody>, а по тегу <table>

Так как вместе эти фильтры конфликтуют и работает только один из них.

рони 27.09.2019 11:09

denis_kontarev,
сделайте макет, структуру вашей таблицы, с минимумом данных, только для примера.

denis_kontarev 27.09.2019 11:21

<input type="text" id="teams_filter" placeholder="Поиск по таблице">

<table class="proanaliz-table tsort" id="table_search">

   <thead>
      <tr>
         <th class="sort">Начало</th>
         <th class="sort">Команды</th>
         <th class="sort">1</th>
         <th class="sort">X</th>
         <th class="sort">2</th>
         <th class="sort">TIP</th>
      </tr>
   </thead>
   
   <tfoot>
      <tr>
         <td>01:00</td>
         <td>>Спортиво Лукеньо - Депортиво Сантани</td>
         <td>2.63</td>
         <td>3.24</td>
         <td>2.99</td>
      </tr>

      <tr>
         <td colspan="6">
            <a href="#" class="spoiler-trigger"><span>Открыть подробную информацию</span></a>	
            <div class="spoiler-block">
               <table class="proanaliz-table">
                  <tr>
                     <td>04:00</td>
                     <td>>Палмейрас - ЦСА</td>
                     <td>1.19</td>
                     <td>2.56</td>
                     <td>3.98</td>
                  </tr>
               </table>
            </div>
         </td>
      </tr>
   </tfoot>
   
</table>

рони 27.09.2019 12:12

сортировка и фильтрация tfoot table
 
denis_kontarev,
<!DOCTYPE html>

<html>
<head>
  <title>Untitled</title>
  <meta charset="utf-8">
  <style type="text/css">
  @import url('https://fonts.googleapis.com/css?family=Roboto:400,400i,500,500i,700');
body {
    font-family: Roboto;
}

table {
    border-collapse: collapse
}

td, th {
    border: 2px solid red;
    width: 150px;
    height: 40px;
    text-align: center;
}

th {
    cursor: pointer;
    user-select: none;
}

th.sorted[data-order="-1"]::after {
    content: "▼"
}

th.sorted[data-order="1"]::after {
    content: "▲"
}


tfoot.hide{
    display: none;
}


.spoiler-trigger + div {
    display: none;
}
.spoiler-trigger.open + div {
    display: block;
}
</style>

  <script>
document.addEventListener('DOMContentLoaded', () => {
    const table = document.querySelector('.tsort');
    const ArrayTfoot = [...table.querySelectorAll('tfoot')];
    const getSort = ({target}) => {
        const order = target.dataset.order = -(target.dataset.order || -1);
        const index = [...target.parentNode.cells].indexOf(target);
        const collator = new Intl.Collator(["en", "ru"], {numeric: true});
        const comparator = (index, order) => (a, b) => order * collator.compare(
            a.querySelector('tr').children[index].innerHTML,
            b.querySelector('tr').children[index].innerHTML);
        ArrayTfoot.sort(comparator(index, order));
        table.append(...ArrayTfoot);
        for (const cell of target.parentNode.cells)
            cell.classList.toggle("sorted", cell === target);
    };
    document.querySelector('.tsort thead').addEventListener('click', getSort);
    const inputFilter = document.querySelector('#teams_filter');
    inputFilter.addEventListener('input', () => ArrayTfoot.forEach(tfoot => {
        const text = tfoot.textContent.toLowerCase(),
            val = inputFilter.value.trim().toLowerCase(),
            hide = val && text.indexOf(val) === -1;
        tfoot.classList.toggle('hide', hide)
    }))
    document.addEventListener('click', event => {
    const target = event.target.closest('.spoiler-trigger');
    if(target) {
    event.preventDefault();
    target.classList.toggle('open')
    }
    })

})
</script>
</head>

<body>
<input type="text" id="teams_filter" placeholder="Поиск по таблице">

<table class="proanaliz-table tsort" id="table_search">

   <thead>
      <tr>
         <th class="sort">Начало</th>
         <th class="sort">Команды</th>
         <th class="sort">1</th>
         <th class="sort">X</th>
         <th class="sort">2</th>
         <th class="sort">TIP</th>
      </tr>
   </thead>

   <tfoot>
      <tr>
         <td>01:00</td>
         <td>>Спортиво Лукеньо - Депортиво Сантани</td>
         <td>2.63</td>
         <td>3.24</td>
         <td>2.99</td>
      </tr>

      <tr>
         <td colspan="6">
            <a href="#" class="spoiler-trigger"><span>Открыть подробную информацию</span></a>
            <div class="spoiler-block">
               <table class="proanaliz-table">
                  <tr>
                     <td>04:00</td>
                     <td>>Палмейрас - ЦСА</td>
                     <td>1.19</td>
                     <td>2.56</td>
                     <td>3.98</td>
                  </tr>
               </table>
            </div>
         </td>
      </tr>
   </tfoot>
   <tfoot>
      <tr>
         <td>08:00</td>
         <td>>индия</td>
         <td>2.63</td>
         <td>3.24</td>
         <td>2.99</td>
      </tr>

      <tr>
         <td colspan="6">
            <a href="#" class="spoiler-trigger"><span>Открыть подробную информацию</span></a>
            <div class="spoiler-block">
               <table class="proanaliz-table">
                  <tr>
                     <td>04:00</td>
                     <td>>Палмейрас - ЦСА</td>
                     <td>1.19</td>
                     <td>2.56</td>
                     <td>3.98</td>
                  </tr>
               </table>
            </div>
         </td>
      </tr>
   </tfoot>
</table>


</body>
</html>

denis_kontarev 27.09.2019 12:42

Рони в очередной раз огромное спасибо!!!! Работает идеально!


Часовой пояс GMT +3, время: 04:20.