Просмотр полной версии : Функция для сортировки таблицы
JStudent
07.11.2018, 17:07
Привет.
Есть функция которая сортирует колонку по возростанию по клику на хэдер.
При повторном клике сортируется по убыванию.
То что я написал мне не сильно нравится.
Как правильно организовать логику сортировки?
https://codepen.io/everest08/pen/KrdPLP
codepen.io/Malleys/pen/dQGMbP (https://codepen.io/Malleys/pen/dQGMbP?editors=1010)
JStudent
07.11.2018, 18:59
Агонь.:victory:
:blink: Не сразу понял откуда берётся 1 в data-order
Спасибо
: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
codepen.io/Malleys/pen/dQGMbP (https://codepen.io/Malleys/pen/dQGMbP?editors=1010)
похоже там баг для чисел.
Сортирует от меньшего большего в таком порядке
1, 1500, 33, 41, 43, 77
изменить в ней значения
так?
<!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
похоже там баг для чисел.
Сортирует от меньшего большего в таком порядке
1, 1500, 33, 41, 43, 77 Вообще-то нет! Оно сортировало в алфавитном порядке. Полезно, если, например, нужно отсортировать список телефонных номеров.
сортировка чисел будет посложнее чем букв.
Для этого есть Internationalization API. Это не сложнее, чем new Intl.Collator(["en", "ru"], { numeric: true });, чтобы сравнивать строки по-русский, по-английский и числа. (ё по-русский будет сравниваться как в алфавите)
На самом деле это очень простая задача и решается она просто! codepen.io/Malleys/pen/dQGMbP (https://codepen.io/Malleys/pen/dQGMbP?editors=0010)
UPDconst [{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);
Да, да, да, именно так и надо!
Malleys,
а если так индекс
const index = [...target.parentNode.cells].indexOf(target);
В чём прикол?
в недостатке понимания и знаний.
Эту сортировку можно организовать так, чтобы ещё потом не нужно было разворачивать массив.
это понятно.
denis_kontarev
27.09.2019, 10:07
А можно ли сделать чтоб поиск шел не по <tbody> , а допустим по какому либо другому тегу <table>?
denis_kontarev
27.09.2019, 10:47
Я и спрашиваю есть ли такая возможность?)
У меня стоит фильтр по буквам "А-Я", который работает по <tfoot> и числовой фильтр, который по <tbody>, но вместе эти теги конфликтуют и не получается задействовать сразу два фильтра
denis_kontarev,
не понимаю.
denis_kontarev
27.09.2019, 11:04
Попробую подробно описать.
Первый фильтр делает поиск по тегу <tfoot> введенные буквы (слова) и при совпадении оставляет нужную информацию.
http://images.vfl.ru/ii/1569571405/e58cc99b/27993041.png
$(document).ready(function(){
$("#teams_filter").keyup(function(){
_this = this;
$.each($("#table_search tfoot"), function() {
if($(this).text().toLowerCase().indexOf($(_this).v al().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>
http://images.vfl.ru/ii/1569571330/35699202/27993024.png
Так как вместе эти фильтры конфликтуют и работает только один из них.
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>
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
Рони в очередной раз огромное спасибо!!!! Работает идеально!
vBulletin® v3.6.7, Copyright ©2000-2025, Jelsoft Enterprises Ltd. Перевод: zCarot